diff --git a/README.md b/README.md index daf50b29979d..8f11a658c1c3 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,9 @@ This client supports the following Google Cloud Platform services at a [Beta](#v - [Google Cloud Datastore](#google-cloud-datastore-beta) (Beta) - [Google Cloud Storage](#google-cloud-storage-beta) (Beta) - [Cloud Spanner](#cloud-spanner-beta) (Beta) +- [Google Cloud Translation](#google-translation-beta) (Beta) - Cloud Vision (Beta) +- Cloud Natural Language (Beta) This client supports the following Google Cloud Platform services at an [Alpha](#versioning) quality level: @@ -27,7 +29,6 @@ This client supports the following Google Cloud Platform services at an [Alpha]( - [Google Cloud DNS](#google-cloud-dns-alpha) (Alpha) - [Google Cloud Pub/Sub](#google-cloud-pubsub-alpha) (Alpha - Not working on App Engine Standard) - [Google Cloud Resource Manager](#google-cloud-resource-manager-alpha) (Alpha) -- [Google Cloud Translate](#google-translate-alpha) (Alpha) > Note: This client is a work-in-progress, and may occasionally > make backwards-incompatible changes. @@ -45,16 +46,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud - 0.10.0-alpha + 0.12.0-alpha ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud:0.10.0-alpha' +compile 'com.google.cloud:google-cloud:0.12.0-alpha' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud" % "0.10.0-alpha" +libraryDependencies += "com.google.cloud" % "google-cloud" % "0.12.0-alpha" ``` For running on Google App Engine, see [more instructions here](./APPENGINE.md). @@ -88,7 +89,7 @@ Example Applications - Read more about using this application on the [`StorageExample` docs page](https://googlecloudplatform.github.io/google-cloud-java/apidocs/?com/google/cloud/examples/storage/StorageExample.html). - [`TaskList`](https://github.com/GoogleCloudPlatform/java-docs-samples/blob/master/datastore/src/main/java/com/google/datastore/snippets/TaskList.java) - A command line application that uses Cloud Datastore to manage a to-do list. - Read about how to run the application on its [README page](https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/datastore). -- [`TranslateExample`](./google-cloud-examples/src/main/java/com/google/cloud/examples/translate/TranslateExample.java) - A simple command line interface providing some of Google Translate's functionality +- [`TranslateExample`](./google-cloud-examples/src/main/java/com/google/cloud/examples/translate/TranslateExample.java) - A simple command line interface providing some of Google Translation's functionality - Read more about using this application on the [`TranslateExample` docs page](https://googlecloudplatform.github.io/google-cloud-java/apidocs/?com/google/cloud/examples/translate/TranslateExample.html). Specifying a Project ID @@ -585,29 +586,31 @@ Google Cloud Pub/Sub (Alpha) Here is a code snippet showing a simple usage example from within Compute Engine/App Engine Flexible. Note that you must [supply credentials](#authentication) and a project ID if running this snippet elsewhere. Complete source code can be found at -[CreateSubscriptionAndPullMessages.java](./google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/CreateSubscriptionAndPullMessages.java). +[CreateTopicAndPublishMessages.java](./google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/CreateTopicAndPublishMessages.java). ```java -import com.google.cloud.pubsub.Message; -import com.google.cloud.pubsub.PubSub; -import com.google.cloud.pubsub.PubSub.MessageConsumer; -import com.google.cloud.pubsub.PubSub.MessageProcessor; -import com.google.cloud.pubsub.PubSubOptions; -import com.google.cloud.pubsub.Subscription; -import com.google.cloud.pubsub.SubscriptionInfo; - -try (PubSub pubsub = PubSubOptions.getDefaultInstance().getService()) { - Subscription subscription = - pubsub.create(SubscriptionInfo.of("test-topic", "test-subscription")); - MessageProcessor callback = new MessageProcessor() { - @Override - public void process(Message message) throws Exception { - System.out.printf("Received message \"%s\"%n", message.getPayloadAsString()); - } - }; - // Create a message consumer and pull messages (for 60 seconds) - try (MessageConsumer consumer = subscription.pullAsync(callback)) { - Thread.sleep(60_000); +import com.google.api.gax.core.ApiFuture; +import com.google.cloud.pubsub.spi.v1.Publisher; +import com.google.cloud.pubsub.spi.v1.TopicAdminClient; +import com.google.protobuf.ByteString; +import com.google.pubsub.v1.PubsubMessage; +import com.google.pubsub.v1.TopicName; + +TopicName topic = TopicName.create("test-project", "test-topic"); +try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + topicAdminClient.createTopic(topic); +} + +Publisher publisher = null; +try { + publisher = Publisher.newBuilder(topic).build(); + ByteString data = ByteString.copyFromUtf8("my message"); + PubsubMessage pubsubMessage = PubsubMessage.newBuilder().setData(data).build(); + ApiFuture messageId = publisher.publish(pubsubMessage); + System.out.println("published with message ID: " + messageId.get()); +} finally { + if (publisher != null) { + publisher.shutdown(); } } ``` @@ -647,7 +650,7 @@ while (projectIterator.hasNext()) { } ``` -Google Translate (Alpha) +Google Translation (Beta) ---------------- - [API Documentation][translate-api] diff --git a/TESTING.md b/TESTING.md index b97f23918268..f9d66b3e1a81 100644 --- a/TESTING.md +++ b/TESTING.md @@ -145,44 +145,36 @@ uses the `RemoteLoggingHelper` to create a metric. ### Testing code that uses Pub/Sub -#### On your machine - -You can test against a temporary local Pub/Sub by following these steps: - -1. Start the local Pub/Sub emulator before running your tests using `LocalPubSubHelper`'s `create` -and `start` methods. This will bind a port for communication with the local Pub/Sub emulator. - ```java - LocalPubSubHelper helper = LocalPubSubHelper.create(); - - helper.start(); // Starts the local Pub/Sub emulator in a separate process - ``` +You can test against a Pub/Sub emulator: -2. Create and use a `PubSub` object with the options given by the `LocalPubSubHelper` instance. For -example: - ```java - PubSub localPubsub = helper.getOptions().getService(); - ``` - -3. Run your tests. +1. [Install Cloud SDK](https://cloud.google.com/sdk/downloads) -4. Stop the local Pub/Sub emulator by calling the `stop()` method, like so: - ```java - helper.stop(); - ``` - -#### On a remote machine +2. Start the emulator: +```shell +$ gcloud beta emulators pubsub start +``` -You can test against a remote Pub/Sub emulator as well. To do this, set the `PubSubOptions` project -endpoint to the hostname of the remote machine, like the example below. +To determine which host/port the emulator is running on: +```shell +$ gcloud beta emulators pubsub env-init +# Sample output: +# export PUBSUB_EMULATOR_HOST=localhost:8759 +``` - ```java - PubSubOptions options = PubSubOptions.newBuilder() - .setProjectId("my-project-id") // must match project ID specified on remote machine - .setHost(":") - .setCredentials(NoCredentials.getInstance()) - .build(); - PubSub localPubsub = options.getService(); - ``` +3. Point your client to the emulator. +```java +ChannelProvider channelProvider = + // SubscriptionAdminSettings works too. + TopicAdminSettings.defaultChannelProviderBuilder() + .setEndpoint(System.getenv("PUBSUB_EMULATOR_HOST")) + .setCredentialsProvider( + FixedCredentialsProvider.create(NoCredentials.getInstance())) + .build(); +TopicAdminClient topicClient = TopicAdminClient.create( + TopicAdminSettings.defaultBuilder().setChannelProvider(channelProvider).build()); +Publisher publisher = + Publisher.newBuilder(topicName).setChannelProvider(channelProvider).build(); +``` ### Testing code that uses Resource Manager @@ -241,10 +233,10 @@ Here is an example that clears the bucket created in Step 3 with a timeout of 5 RemoteStorageHelper.forceDelete(storage, bucket, 5, TimeUnit.SECONDS); ``` -### Testing code that uses Translate +### Testing code that uses Translation `RemoteTranslateHelper` contains convenience methods to make is easier to run tests against the -Google Translate service. +Google Translation service. 1. Create a test Google Cloud project. diff --git a/google-cloud-bigquery/README.md b/google-cloud-bigquery/README.md index 6d360f4179d8..4c3335ef39a6 100644 --- a/google-cloud-bigquery/README.md +++ b/google-cloud-bigquery/README.md @@ -22,16 +22,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-bigquery - 0.10.0-beta + 0.12.0-beta ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-bigquery:0.10.0-beta' +compile 'com.google.cloud:google-cloud-bigquery:0.12.0-beta' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-bigquery" % "0.10.0-beta" +libraryDependencies += "com.google.cloud" % "google-cloud-bigquery" % "0.12.0-beta" ``` Example Application diff --git a/google-cloud-bigquery/pom.xml b/google-cloud-bigquery/pom.xml index 64b29c3a1e10..f4c6080eec9e 100644 --- a/google-cloud-bigquery/pom.xml +++ b/google-cloud-bigquery/pom.xml @@ -12,7 +12,7 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-bigquery diff --git a/google-cloud-compute/README.md b/google-cloud-compute/README.md index 6d91631c0166..4dc7dc6fcbf2 100644 --- a/google-cloud-compute/README.md +++ b/google-cloud-compute/README.md @@ -22,16 +22,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-compute - 0.10.0-alpha + 0.12.0-alpha ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-compute:0.10.0-alpha' +compile 'com.google.cloud:google-cloud-compute:0.12.0-alpha' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-compute" % "0.10.0-alpha" +libraryDependencies += "com.google.cloud" % "google-cloud-compute" % "0.12.0-alpha" ``` Example Application diff --git a/google-cloud-compute/pom.xml b/google-cloud-compute/pom.xml index d639cb8ddd12..17101a4b4e95 100644 --- a/google-cloud-compute/pom.xml +++ b/google-cloud-compute/pom.xml @@ -11,7 +11,7 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-compute diff --git a/google-cloud-compute/src/main/java/com/google/cloud/compute/testing/ResourceCleaner.java b/google-cloud-compute/src/main/java/com/google/cloud/compute/testing/ResourceCleaner.java new file mode 100644 index 000000000000..df0f8682ffe0 --- /dev/null +++ b/google-cloud-compute/src/main/java/com/google/cloud/compute/testing/ResourceCleaner.java @@ -0,0 +1,171 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.compute.testing; + +import com.google.cloud.compute.AddressId; +import com.google.cloud.compute.Compute; +import com.google.cloud.compute.DiskId; +import com.google.cloud.compute.ImageId; +import com.google.cloud.compute.InstanceId; +import com.google.cloud.compute.NetworkId; +import com.google.cloud.compute.SnapshotId; +import com.google.cloud.compute.SubnetworkId; +import com.google.common.base.Function; +import java.util.HashMap; +import java.util.Map; +import java.util.NoSuchElementException; + +public class ResourceCleaner { + private final Compute compute; + private final Map> resources; + + private ResourceCleaner(Compute compute) { + this.compute = compute; + this.resources = new HashMap<>(); + } + + public static ResourceCleaner create(Compute compute) { + return new ResourceCleaner(compute); + } + + private class ManagedResource { + final T resourceId; + Function deleteFunc; + + private ManagedResource(T resourceId, Function deleteFunc) { + this.resourceId = resourceId; + this.deleteFunc = deleteFunc; + } + + public void delete() { + deleteFunc.apply(resourceId); + } + } + + public void cleanUp() { + for (Map.Entry> r : resources.entrySet()) { + r.getValue().delete(); + } + resources.clear(); + } + + public void add(AddressId addressId) { + ManagedResource r = + new ManagedResource<>( + addressId, + new Function() { + @Override + public Void apply(AddressId addressId) { + compute.deleteAddress(addressId); + return null; + } + }); + resources.put(addressId, r); + } + + public void add(DiskId diskId) { + ManagedResource r = + new ManagedResource<>( + diskId, + new Function() { + @Override + public Void apply(DiskId diskId) { + compute.deleteDisk(diskId); + return null; + } + }); + resources.put(diskId, r); + } + + public void add(SnapshotId snapshotId) { + ManagedResource r = + new ManagedResource<>( + snapshotId, + new Function() { + @Override + public Void apply(SnapshotId snapshotId) { + compute.deleteSnapshot(snapshotId); + return null; + } + }); + resources.put(snapshotId, r); + } + + public void add(NetworkId networkId) { + ManagedResource r = + new ManagedResource<>( + networkId, + new Function() { + @Override + public Void apply(NetworkId networkId) { + compute.deleteNetwork(networkId); + return null; + } + }); + resources.put(networkId, r); + } + + public void add(SubnetworkId subnetworkId) { + ManagedResource r = + new ManagedResource<>( + subnetworkId, + new Function() { + @Override + public Void apply(SubnetworkId subnetworkId) { + compute.deleteSubnetwork(subnetworkId); + return null; + } + }); + resources.put(subnetworkId, r); + } + + public void add(ImageId imageId) { + ManagedResource r = + new ManagedResource<>( + imageId, + new Function() { + @Override + public Void apply(ImageId imageId) { + compute.deleteImage(imageId); + return null; + } + }); + resources.put(imageId, r); + } + + public void add(InstanceId instanceId) { + ManagedResource r = + new ManagedResource<>( + instanceId, + new Function() { + @Override + public Void apply(InstanceId instanceId) { + compute.deleteInstance(instanceId); + return null; + } + }); + resources.put(instanceId, r); + } + + public ResourceCleaner remove(Object resourceId) { + if (!resources.containsKey(resourceId)) { + throw new NoSuchElementException(resourceId + " has not been added to managed resources"); + } + resources.remove(resourceId); + return this; + } +} diff --git a/google-cloud-compute/src/test/java/com/google/cloud/compute/it/ITComputeTest.java b/google-cloud-compute/src/test/java/com/google/cloud/compute/it/ITComputeTest.java index 1d7eb4b293ed..18c576f99b37 100644 --- a/google-cloud-compute/src/test/java/com/google/cloud/compute/it/ITComputeTest.java +++ b/google-cloud-compute/src/test/java/com/google/cloud/compute/it/ITComputeTest.java @@ -73,21 +73,21 @@ import com.google.cloud.compute.SubnetworkInfo; import com.google.cloud.compute.Zone; import com.google.cloud.compute.ZoneOperationId; +import com.google.cloud.compute.testing.ResourceCleaner; import com.google.cloud.compute.testing.RemoteComputeHelper; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; - -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.Timeout; - import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeoutException; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.Timeout; public class ITComputeTest { @@ -101,6 +101,8 @@ public class ITComputeTest { private static final String IMAGE_PROJECT = "debian-cloud"; private static Compute compute; + private static ResourceCleaner resourceCleaner; + @Rule public Timeout globalTimeout = Timeout.seconds(300); @@ -109,6 +111,12 @@ public class ITComputeTest { public static void beforeClass() { RemoteComputeHelper computeHelper = RemoteComputeHelper.create(); compute = computeHelper.getOptions().getService(); + resourceCleaner = ResourceCleaner.create(compute); + } + + @AfterClass + public static void tearDown() { + resourceCleaner.cleanUp(); } @Test @@ -689,6 +697,7 @@ public void testCreateGetAndDeleteRegionAddress() throws InterruptedException, T operation.waitFor(); // test get Address remoteAddress = compute.getAddress(addressId); + resourceCleaner.add(addressId); assertNotNull(remoteAddress); assertTrue(remoteAddress.getAddressId() instanceof RegionAddressId); assertEquals(REGION, remoteAddress.getAddressId().getRegion()); @@ -708,6 +717,7 @@ public void testCreateGetAndDeleteRegionAddress() throws InterruptedException, T assertNull(remoteAddress.getGeneratedId()); operation = remoteAddress.delete(); operation.waitFor(); + resourceCleaner.remove(addressId); assertNull(compute.getAddress(addressId)); } @@ -720,7 +730,9 @@ public void testListRegionAddresses() throws InterruptedException, TimeoutExcept Operation firstOperation = compute.create(AddressInfo.of(firstAddressId)); Operation secondOperation = compute.create(AddressInfo.of(secondAddressId)); firstOperation.waitFor(); + resourceCleaner.add(firstAddressId); secondOperation.waitFor(); + resourceCleaner.add(secondAddressId); Set addressSet = ImmutableSet.copyOf(addressNames); // test list Compute.AddressFilter filter = @@ -759,8 +771,6 @@ public void testListRegionAddresses() throws InterruptedException, TimeoutExcept count++; } assertEquals(2, count); - compute.deleteAddress(firstAddressId); - compute.deleteAddress(secondAddressId); } @Test @@ -772,7 +782,9 @@ public void testAggregatedListAddresses() throws InterruptedException, TimeoutEx Operation firstOperation = compute.create(AddressInfo.of(firstAddressId)); Operation secondOperation = compute.create(AddressInfo.of(secondAddressId)); firstOperation.waitFor(); + resourceCleaner.add(firstAddressId); secondOperation.waitFor(); + resourceCleaner.add(secondAddressId); Set addressSet = ImmutableSet.copyOf(addressNames); Compute.AddressFilter filter = Compute.AddressFilter.equals(Compute.AddressField.NAME, prefix + "\\d"); @@ -790,8 +802,6 @@ public void testAggregatedListAddresses() throws InterruptedException, TimeoutEx count++; } assertEquals(2, count); - compute.deleteAddress(firstAddressId); - compute.deleteAddress(secondAddressId); } @Test @@ -803,6 +813,7 @@ public void testCreateGetAndDeleteGlobalAddress() throws InterruptedException, T operation.waitFor(); // test get Address remoteAddress = compute.getAddress(addressId); + resourceCleaner.add(addressId); assertNotNull(remoteAddress); assertTrue(remoteAddress.getAddressId() instanceof GlobalAddressId); assertEquals(addressId.getAddress(), remoteAddress.getAddressId().getAddress()); @@ -820,6 +831,7 @@ public void testCreateGetAndDeleteGlobalAddress() throws InterruptedException, T assertNull(remoteAddress.getGeneratedId()); operation = remoteAddress.delete(); operation.waitFor(); + resourceCleaner.remove(addressId); assertNull(compute.getAddress(addressId)); } @@ -832,7 +844,9 @@ public void testListGlobalAddresses() throws InterruptedException, TimeoutExcept Operation firstOperation = compute.create(AddressInfo.of(firstAddressId)); Operation secondOperation = compute.create(AddressInfo.of(secondAddressId)); firstOperation.waitFor(); + resourceCleaner.add(firstAddressId); secondOperation.waitFor(); + resourceCleaner.add(secondAddressId); Set addressSet = ImmutableSet.copyOf(addressNames); // test list Compute.AddressFilter filter = @@ -869,8 +883,6 @@ public void testListGlobalAddresses() throws InterruptedException, TimeoutExcept count++; } assertEquals(2, count); - compute.deleteAddress(firstAddressId); - compute.deleteAddress(secondAddressId); } @Test @@ -884,6 +896,7 @@ public void testCreateGetResizeAndDeleteStandardDisk() operation.waitFor(); // test get Disk remoteDisk = compute.getDisk(diskId); + resourceCleaner.add(diskId); assertNotNull(remoteDisk); assertEquals(ZONE, remoteDisk.getDiskId().getZone()); assertEquals(diskId.getDisk(), remoteDisk.getDiskId().getDisk()); @@ -914,6 +927,7 @@ public void testCreateGetResizeAndDeleteStandardDisk() assertNull(remoteDisk.getLastDetachTimestamp()); operation = remoteDisk.delete(); operation.waitFor(); + resourceCleaner.remove(diskId); assertNull(compute.getDisk(diskId)); } @@ -926,6 +940,7 @@ public void testCreateGetAndDeleteImageDisk() throws InterruptedException, Timeo operation.waitFor(); // test get Disk remoteDisk = compute.getDisk(diskId); + resourceCleaner.add(diskId); assertNotNull(remoteDisk); assertEquals(ZONE, remoteDisk.getDiskId().getZone()); assertEquals(diskId.getDisk(), remoteDisk.getDiskId().getDisk()); @@ -959,6 +974,7 @@ public void testCreateGetAndDeleteImageDisk() throws InterruptedException, Timeo assertNull(remoteDisk.getLastDetachTimestamp()); operation = remoteDisk.delete(); operation.waitFor(); + resourceCleaner.remove(diskId); assertNull(compute.getDisk(diskId)); } @@ -975,11 +991,13 @@ public void testCreateGetAndDeleteSnapshotAndSnapshotDisk() Operation operation = compute.create(diskInfo); operation.waitFor(); Disk remoteDisk = compute.getDisk(diskId); + resourceCleaner.add(diskId); operation = remoteDisk.createSnapshot(snapshotName); operation.waitFor(); // test get snapshot with selected fields Snapshot snapshot = compute.getSnapshot(snapshotName, Compute.SnapshotOption.fields(Compute.SnapshotField.CREATION_TIMESTAMP)); + resourceCleaner.add(snapshot.getSnapshotId()); assertNull(snapshot.getGeneratedId()); assertNotNull(snapshot.getSnapshotId()); assertNotNull(snapshot.getCreationTimestamp()); @@ -1003,12 +1021,14 @@ public void testCreateGetAndDeleteSnapshotAndSnapshotDisk() assertNotNull(snapshot.getStorageBytes()); assertNotNull(snapshot.getStorageBytesStatus()); remoteDisk.delete(); + resourceCleaner.remove(diskId); diskInfo = DiskInfo.of(snapshotDiskId, SnapshotDiskConfiguration.of(SnapshotId.of(snapshotName))); operation = compute.create(diskInfo); -operation.waitFor(); + operation.waitFor(); // test get disk remoteDisk = compute.getDisk(snapshotDiskId); + resourceCleaner.add(snapshotDiskId); assertNotNull(remoteDisk); assertEquals(ZONE, remoteDisk.getDiskId().getZone()); assertEquals(snapshotDiskId.getDisk(), remoteDisk.getDiskId().getDisk()); @@ -1042,10 +1062,12 @@ public void testCreateGetAndDeleteSnapshotAndSnapshotDisk() assertNull(remoteDisk.getLastAttachTimestamp()); assertNull(remoteDisk.getLastDetachTimestamp()); operation = remoteDisk.delete(); -operation.waitFor(); + operation.waitFor(); + resourceCleaner.remove(snapshotDiskId); assertNull(compute.getDisk(snapshotDiskId)); operation = snapshot.delete(); -operation.waitFor(); + operation.waitFor(); + resourceCleaner.remove(snapshot.getSnapshotId()); assertNull(compute.getSnapshot(snapshotName)); } @@ -1060,7 +1082,9 @@ public void testListDisksAndSnapshots() throws InterruptedException, TimeoutExce Operation firstOperation = compute.create(DiskInfo.of(firstDiskId, configuration)); Operation secondOperation = compute.create(DiskInfo.of(secondDiskId, configuration)); firstOperation.waitFor(); + resourceCleaner.add(firstDiskId); secondOperation.waitFor(); + resourceCleaner.add(secondDiskId); Set diskSet = ImmutableSet.copyOf(diskNames); // test list disks Compute.DiskFilter diskFilter = @@ -1113,7 +1137,9 @@ public void testListDisksAndSnapshots() throws InterruptedException, TimeoutExce firstOperation = compute.create(SnapshotInfo.of(firstSnapshotId, firstDiskId)); secondOperation = compute.create(SnapshotInfo.of(secondSnapshotId, secondDiskId)); firstOperation.waitFor(); + resourceCleaner.add(firstSnapshotId); secondOperation.waitFor(); + resourceCleaner.add(secondSnapshotId); // test list snapshots Compute.SnapshotFilter snapshotFilter = Compute.SnapshotFilter.equals(Compute.SnapshotField.NAME, prefix + "\\d"); @@ -1154,10 +1180,6 @@ public void testListDisksAndSnapshots() throws InterruptedException, TimeoutExce count++; } assertEquals(2, count); - compute.deleteDisk(firstDiskId); - compute.deleteDisk(secondDiskId); - compute.deleteSnapshot(firstSnapshotId); - compute.deleteSnapshot(secondSnapshotId); } @Test @@ -1172,7 +1194,9 @@ public void testAggregatedListDisks() throws InterruptedException, TimeoutExcept Operation firstOperation = compute.create(DiskInfo.of(firstDiskId, configuration)); Operation secondOperation = compute.create(DiskInfo.of(secondDiskId, configuration)); firstOperation.waitFor(); + resourceCleaner.add(firstDiskId); secondOperation.waitFor(); + resourceCleaner.add(secondDiskId); Set zoneSet = ImmutableSet.copyOf(diskZones); Set diskSet = ImmutableSet.copyOf(diskNames); Compute.DiskFilter diskFilter = @@ -1195,8 +1219,6 @@ public void testAggregatedListDisks() throws InterruptedException, TimeoutExcept count++; } assertEquals(2, count); - compute.deleteDisk(firstDiskId); - compute.deleteDisk(secondDiskId); } @Test @@ -1213,9 +1235,11 @@ public void testCreateGetAndDeprecateImage() throws InterruptedException, Timeou ImageInfo imageInfo = ImageInfo.of(imageId, DiskImageConfiguration.of(diskId)); operation = compute.create(imageInfo); operation.waitFor(); + resourceCleaner.add(diskId); // test get image with selected fields Image image = compute.getImage(imageId, Compute.ImageOption.fields(Compute.ImageField.CREATION_TIMESTAMP)); + resourceCleaner.add(imageId); assertNull(image.getGeneratedId()); assertNotNull(image.getImageId()); assertNotNull(image.getCreationTimestamp()); @@ -1248,12 +1272,14 @@ public void testCreateGetAndDeprecateImage() throws InterruptedException, Timeou .setDeprecated(System.currentTimeMillis()) .build(); operation = image.deprecate(deprecationStatus); -operation.waitFor(); + operation.waitFor(); image = compute.getImage(imageId); assertEquals(deprecationStatus, image.getDeprecationStatus()); remoteDisk.delete(); + resourceCleaner.remove(diskId); operation = image.delete(); -operation.waitFor(); + operation.waitFor(); + resourceCleaner.remove(imageId); assertNull(compute.getImage(imageId)); } @@ -1328,6 +1354,7 @@ public void testCreateAndGetNetwork() throws InterruptedException, TimeoutExcept // test get network with selected fields Network network = compute.getNetwork(networkId.getNetwork(), Compute.NetworkOption.fields(Compute.NetworkField.CREATION_TIMESTAMP)); + resourceCleaner.add(networkId); assertEquals(networkId.getNetwork(), network.getNetworkId().getNetwork()); assertNull(network.getGeneratedId()); assertNotNull(network.getCreationTimestamp()); @@ -1344,7 +1371,8 @@ public void testCreateAndGetNetwork() throws InterruptedException, TimeoutExcept remoteConfiguration = network.getConfiguration(); assertEquals("192.168.0.0/16", remoteConfiguration.getIpRange()); operation = network.delete(); -operation.waitFor(); + operation.waitFor(); + resourceCleaner.remove(networkId); assertNull(compute.getNetwork(name)); } @@ -1355,7 +1383,8 @@ public void testListNetworks() throws InterruptedException, TimeoutException { NetworkInfo networkInfo = NetworkInfo.of(networkId, StandardNetworkConfiguration.of("192.168.0.0/16")); Operation operation = compute.create(networkInfo); -operation.waitFor(); + operation.waitFor(); + resourceCleaner.add(networkId); // test list Compute.NetworkFilter filter = Compute.NetworkFilter.equals(Compute.NetworkField.NAME, name); Page networkPage = compute.listNetworks(Compute.NetworkListOption.filter(filter)); @@ -1390,7 +1419,8 @@ public void testListNetworks() throws InterruptedException, TimeoutException { } assertEquals(1, count); operation = compute.deleteNetwork(networkId); -operation.waitFor(); + operation.waitFor(); + resourceCleaner.remove(networkId); assertNull(compute.getNetwork(name)); } @@ -1400,9 +1430,10 @@ public void testCreateNetworkAndSubnetwork() throws InterruptedException, Timeou NetworkId networkId = NetworkId.of(networkName); NetworkInfo networkInfo = NetworkInfo.of(networkId, SubnetNetworkConfiguration.of(false)); Operation operation = compute.create(networkInfo); -operation.waitFor(); + operation.waitFor(); // test get network Network network = compute.getNetwork(networkId.getNetwork()); + resourceCleaner.add(networkId); assertEquals(networkId.getNetwork(), network.getNetworkId().getNetwork()); assertNotNull(network.getGeneratedId()); assertNotNull(network.getCreationTimestamp()); @@ -1413,10 +1444,11 @@ public void testCreateNetworkAndSubnetwork() throws InterruptedException, Timeou SubnetworkId subnetworkId = SubnetworkId.of(REGION, subnetworkName); SubnetworkInfo subnetworkInfo = SubnetworkInfo.of(subnetworkId, networkId, "192.168.0.0/16"); operation = compute.create(subnetworkInfo); -operation.waitFor(); + operation.waitFor(); // test get subnetwork with selected fields Subnetwork subnetwork = compute.getSubnetwork(subnetworkId, Compute.SubnetworkOption.fields(Compute.SubnetworkField.CREATION_TIMESTAMP)); + resourceCleaner.add(subnetworkId); assertNull(subnetwork.getGeneratedId()); assertEquals(subnetworkId.getSubnetwork(), subnetwork.getSubnetworkId().getSubnetwork()); assertNotNull(subnetwork.getCreationTimestamp()); @@ -1470,9 +1502,11 @@ public void testCreateNetworkAndSubnetwork() throws InterruptedException, Timeou } assertEquals(1, count); operation = subnetwork.delete(); -operation.waitFor(); + operation.waitFor(); + resourceCleaner.remove(subnetworkId); operation = compute.deleteNetwork(networkId); -operation.waitFor(); + operation.waitFor(); + resourceCleaner.remove(networkId); assertNull(compute.getSubnetwork(subnetworkId)); assertNull(compute.getNetwork(networkName)); } @@ -1483,7 +1517,8 @@ public void testAggregatedListSubnetworks() throws InterruptedException, Timeout NetworkId networkId = NetworkId.of(networkName); NetworkInfo networkInfo = NetworkInfo.of(networkId, SubnetNetworkConfiguration.of(false)); Operation operation = compute.create(networkInfo); -operation.waitFor(); + operation.waitFor(); + resourceCleaner.add(networkId); String prefix = BASE_RESOURCE_NAME + "list-subnetwork"; String[] regionNames = {"us-central1", "us-east1"}; String[] subnetworkNames = {prefix + "1", prefix + "2"}; @@ -1497,7 +1532,9 @@ public void testAggregatedListSubnetworks() throws InterruptedException, Timeout Operation firstOperation = compute.create(firstSubnetworkInfo); Operation secondOperation = compute.create(secondSubnetworkInfo); firstOperation.waitFor(); + resourceCleaner.add(firstSubnetworkId); secondOperation.waitFor(); + resourceCleaner.add(secondSubnetworkId); Set regionSet = ImmutableSet.copyOf(regionNames); Set subnetworkSet = ImmutableSet.copyOf(subnetworkNames); Set rangeSet = ImmutableSet.copyOf(ipRanges); @@ -1522,9 +1559,12 @@ public void testAggregatedListSubnetworks() throws InterruptedException, Timeout firstOperation = compute.deleteSubnetwork(firstSubnetworkId); secondOperation = compute.deleteSubnetwork(secondSubnetworkId); firstOperation.waitFor(); + resourceCleaner.remove(firstSubnetworkId); secondOperation.waitFor(); + resourceCleaner.remove(secondSubnetworkId); operation = compute.deleteNetwork(networkId); -operation.waitFor(); + operation.waitFor(); + resourceCleaner.remove(networkId); assertNull(compute.getNetwork(networkName)); } @@ -1536,8 +1576,9 @@ public void testCreateGetAndDeleteInstance() throws InterruptedException, Timeou AddressId addressId = RegionAddressId.of(REGION, addressName); AddressInfo addressInfo = AddressInfo.of(addressId); Operation operation = compute.create(addressInfo); -operation.waitFor(); + operation.waitFor(); Address address = compute.getAddress(addressId); + resourceCleaner.add(addressId); // Create an instance InstanceId instanceId = InstanceId.of(ZONE, instanceName); NetworkId networkId = NetworkId.of("default"); @@ -1557,9 +1598,10 @@ public void testCreateGetAndDeleteInstance() throws InterruptedException, Timeou .setNetworkInterfaces(networkInterface) .build(); operation = compute.create(instanceInfo); -operation.waitFor(); + operation.waitFor(); // test get Instance remoteInstance = compute.getInstance(instanceId); + resourceCleaner.add(instanceId); assertEquals(instanceName, remoteInstance.getInstanceId().getInstance()); assertEquals(ZONE, remoteInstance.getInstanceId().getZone()); assertEquals(InstanceInfo.Status.RUNNING, remoteInstance.getStatus()); @@ -1610,9 +1652,9 @@ public void testCreateGetAndDeleteInstance() throws InterruptedException, Timeou String newSerialPortOutput = remoteInstance.getSerialPortOutput(1); assertTrue(newSerialPortOutput.contains(serialPortOutput)); operation = remoteInstance.delete(); -operation.waitFor(); + operation.waitFor(); + resourceCleaner.remove(instanceId); assertNull(compute.getInstance(instanceId)); - address.delete(); } @Test @@ -1629,26 +1671,26 @@ public void testStartStopAndResetInstance() throws InterruptedException, Timeout .setNetworkInterfaces(networkInterface) .build(); Operation operation = compute.create(instanceInfo); -operation.waitFor(); + operation.waitFor(); Instance remoteInstance = compute.getInstance(instanceId, Compute.InstanceOption.fields(Compute.InstanceField.STATUS)); + resourceCleaner.add(instanceId); assertEquals(InstanceInfo.Status.RUNNING, remoteInstance.getStatus()); operation = remoteInstance.stop(); -operation.waitFor(); + operation.waitFor(); remoteInstance = compute.getInstance(instanceId, Compute.InstanceOption.fields(Compute.InstanceField.STATUS)); assertEquals(InstanceInfo.Status.TERMINATED, remoteInstance.getStatus()); operation = remoteInstance.start(); -operation.waitFor(); + operation.waitFor(); remoteInstance = compute.getInstance(instanceId, Compute.InstanceOption.fields(Compute.InstanceField.STATUS)); assertEquals(InstanceInfo.Status.RUNNING, remoteInstance.getStatus()); operation = remoteInstance.reset(); -operation.waitFor(); + operation.waitFor(); remoteInstance = compute.getInstance(instanceId, Compute.InstanceOption.fields(Compute.InstanceField.STATUS)); assertEquals(InstanceInfo.Status.RUNNING, remoteInstance.getStatus()); - remoteInstance.delete(); } @Test @@ -1665,25 +1707,26 @@ public void testSetInstanceProperties() throws InterruptedException, TimeoutExce .setNetworkInterfaces(networkInterface) .build(); Operation operation = compute.create(instanceInfo); -operation.waitFor(); + operation.waitFor(); Instance remoteInstance = compute.getInstance(instanceId); + resourceCleaner.add(instanceId); // test set tags List tags = ImmutableList.of("tag1", "tag2"); operation = remoteInstance.setTags(tags); -operation.waitFor(); + operation.waitFor(); remoteInstance = compute.getInstance(instanceId); assertEquals(tags, remoteInstance.getTags().getValues()); // test set metadata Map metadata = ImmutableMap.of("key", "value"); operation = remoteInstance.setMetadata(metadata); -operation.waitFor(); + operation.waitFor(); remoteInstance = compute.getInstance(instanceId); assertEquals(metadata, remoteInstance.getMetadata().getValues()); // test set machine type operation = remoteInstance.stop(); -operation.waitFor(); + operation.waitFor(); operation = remoteInstance.setMachineType(MachineTypeId.of(ZONE, "n1-standard-1")); -operation.waitFor(); + operation.waitFor(); remoteInstance = compute.getInstance(instanceId); assertEquals("n1-standard-1", remoteInstance.getMachineType().getType()); assertEquals(ZONE, remoteInstance.getMachineType().getZone()); @@ -1691,10 +1734,9 @@ public void testSetInstanceProperties() throws InterruptedException, TimeoutExce SchedulingOptions options = SchedulingOptions.standard(false, SchedulingOptions.Maintenance.TERMINATE); operation = remoteInstance.setSchedulingOptions(options); -operation.waitFor(); + operation.waitFor(); remoteInstance = compute.getInstance(instanceId); assertEquals(options, remoteInstance.getSchedulingOptions()); - remoteInstance.delete(); } @Test @@ -1717,12 +1759,14 @@ public void testAttachAndDetachDisk() throws InterruptedException, TimeoutExcept StandardDiskConfiguration.of(DiskTypeId.of(ZONE, "pd-ssd")))); instanceOperation.waitFor(); diskOperation.waitFor(); + resourceCleaner.add(diskId); Instance remoteInstance = compute.getInstance(instanceId); // test attach disk instanceOperation = remoteInstance.attachDisk("dev1", AttachedDisk.PersistentDiskConfiguration.newBuilder(diskId).build()); instanceOperation.waitFor(); remoteInstance = compute.getInstance(instanceId); + resourceCleaner.add(instanceId); Set deviceSet = ImmutableSet.of("dev0", "dev1"); assertEquals(2, remoteInstance.getAttachedDisks().size()); for (AttachedDisk remoteAttachedDisk : remoteInstance.getAttachedDisks()) { @@ -1743,8 +1787,6 @@ public void testAttachAndDetachDisk() throws InterruptedException, TimeoutExcept remoteInstance = compute.getInstance(instanceId); assertEquals(1, remoteInstance.getAttachedDisks().size()); assertEquals("dev0", remoteInstance.getAttachedDisks().get(0).getDeviceName()); - remoteInstance.delete(); - compute.deleteDisk(diskId); } @Test @@ -1768,7 +1810,9 @@ public void testAddAndRemoveAccessConfig() throws InterruptedException, TimeoutE addressOperation.waitFor(); instanceOperation.waitFor(); Address remoteAddress = compute.getAddress(addressId); + resourceCleaner.add(addressId); Instance remoteInstance = compute.getInstance(instanceId); + resourceCleaner.add(instanceId); String networkInterfaceName = remoteInstance.getNetworkInterfaces().get(0).getName(); // test add access config NetworkInterface.AccessConfig accessConfig = NetworkInterface.AccessConfig.newBuilder() @@ -1787,7 +1831,5 @@ public void testAddAndRemoveAccessConfig() throws InterruptedException, TimeoutE instanceOperation.waitFor(); remoteInstance = compute.getInstance(instanceId); assertTrue(remoteInstance.getNetworkInterfaces().get(0).getAccessConfigurations().isEmpty()); - remoteInstance.delete(); - remoteAddress.delete(); } } diff --git a/google-cloud-contrib/README.md b/google-cloud-contrib/README.md index c4d96f6e189c..de4d884530d3 100644 --- a/google-cloud-contrib/README.md +++ b/google-cloud-contrib/README.md @@ -25,16 +25,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-contrib - 0.10.0-alpha + 0.12.0-alpha ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-contrib:0.10.0-alpha' +compile 'com.google.cloud:google-cloud-contrib:0.12.0-alpha' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-contrib" % "0.10.0-alpha" +libraryDependencies += "com.google.cloud" % "google-cloud-contrib" % "0.12.0-alpha" ``` ### google-cloud-nio-examples diff --git a/google-cloud-contrib/google-cloud-nio-examples/README.md b/google-cloud-contrib/google-cloud-nio-examples/README.md index c52064316a5c..5bdbcf3a2e67 100644 --- a/google-cloud-contrib/google-cloud-nio-examples/README.md +++ b/google-cloud-contrib/google-cloud-nio-examples/README.md @@ -22,12 +22,12 @@ To run this example: 4. Run the sample with: ``` - java -cp google-cloud-contrib/google-cloud-nio/target/google-cloud-nio-0.10.1-alpha-SNAPSHOT-shaded.jar:google-cloud-contrib/google-cloud-nio-examples/target/google-cloud-nio-examples-0.10.1-alpha-SNAPSHOT.jar com.google.cloud.nio.examples.ListFilesystems + java -cp google-cloud-contrib/google-cloud-nio/target/google-cloud-nio-0.12.1-alpha-SNAPSHOT-shaded.jar:google-cloud-contrib/google-cloud-nio-examples/target/google-cloud-nio-examples-0.12.1-alpha-SNAPSHOT.jar com.google.cloud.nio.examples.ListFilesystems ``` Notice that it lists Google Cloud Storage, which it wouldn't if you ran it without the NIO jar: ``` - java -cp google-cloud-contrib/google-cloud-nio-examples/target/google-cloud-nio-examples-0.10.1-alpha-SNAPSHOT.jar com.google.cloud.nio.examples.ListFilesystems + java -cp google-cloud-contrib/google-cloud-nio-examples/target/google-cloud-nio-examples-0.12.1-alpha-SNAPSHOT.jar com.google.cloud.nio.examples.ListFilesystems ``` The sample doesn't have anything about Google Cloud Storage in it. It gets that ability from the NIO diff --git a/google-cloud-contrib/google-cloud-nio-examples/pom.xml b/google-cloud-contrib/google-cloud-nio-examples/pom.xml index 5f20f35f58c4..d6e467861491 100644 --- a/google-cloud-contrib/google-cloud-nio-examples/pom.xml +++ b/google-cloud-contrib/google-cloud-nio-examples/pom.xml @@ -11,7 +11,7 @@ com.google.cloud google-cloud-contrib - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-nio-examples diff --git a/google-cloud-contrib/google-cloud-nio/README.md b/google-cloud-contrib/google-cloud-nio/README.md index db70e37a5e9c..ce906084a6a9 100644 --- a/google-cloud-contrib/google-cloud-nio/README.md +++ b/google-cloud-contrib/google-cloud-nio/README.md @@ -26,16 +26,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-nio - 0.10.0-alpha + 0.12.0-alpha ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-nio:0.10.0-alpha' +compile 'com.google.cloud:google-cloud-nio:0.12.0-alpha' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-nio" % "0.10.0-alpha" +libraryDependencies += "com.google.cloud" % "google-cloud-nio" % "0.12.0-alpha" ``` Example Applications diff --git a/google-cloud-contrib/google-cloud-nio/pom.xml b/google-cloud-contrib/google-cloud-nio/pom.xml index 18e0fe8040e2..6ae7f78ff72c 100644 --- a/google-cloud-contrib/google-cloud-nio/pom.xml +++ b/google-cloud-contrib/google-cloud-nio/pom.xml @@ -11,7 +11,7 @@ com.google.cloud google-cloud-contrib - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-nio diff --git a/google-cloud-contrib/google-cloud-nio/src/test/java/com/google/cloud/storage/contrib/nio/FakeStorageRpc.java b/google-cloud-contrib/google-cloud-nio/src/test/java/com/google/cloud/storage/contrib/nio/FakeStorageRpc.java index 3e7c603cae3f..4ce3abae3dc2 100644 --- a/google-cloud-contrib/google-cloud-nio/src/test/java/com/google/cloud/storage/contrib/nio/FakeStorageRpc.java +++ b/google-cloud-contrib/google-cloud-nio/src/test/java/com/google/cloud/storage/contrib/nio/FakeStorageRpc.java @@ -19,7 +19,9 @@ import com.google.api.services.storage.model.Bucket; import com.google.api.services.storage.model.BucketAccessControl; import com.google.api.services.storage.model.ObjectAccessControl; +import com.google.api.services.storage.model.Policy; import com.google.api.services.storage.model.StorageObject; +import com.google.api.services.storage.model.TestIamPermissionsResponse; import com.google.cloud.storage.Storage; import com.google.cloud.storage.StorageException; import com.google.cloud.storage.spi.v1.RpcBatch; @@ -61,6 +63,7 @@ *
  • continueRewrite *
  • createBatch *
  • checksums, etags + *
  • IAM operations
  • * * */ @@ -443,4 +446,19 @@ private static boolean processedAsFolder(StorageObject so, String delimiter, Str folders.put(folderName, fakeFolder); return true; } + + @Override + public Policy getPolicy(String bucket) { + throw new UnsupportedOperationException(); + } + + @Override + public Policy updatePolicy(String bucket, Policy policy) { + throw new UnsupportedOperationException(); + } + + @Override + public TestIamPermissionsResponse testPermissions(String bucket, List permissions) { + throw new UnsupportedOperationException(); + } } diff --git a/google-cloud-contrib/pom.xml b/google-cloud-contrib/pom.xml index e3dd54b8d204..7bbd92a8daa8 100644 --- a/google-cloud-contrib/pom.xml +++ b/google-cloud-contrib/pom.xml @@ -11,7 +11,7 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-contrib diff --git a/google-cloud-core/README.md b/google-cloud-core/README.md index ea1b3d922c2f..60076c965e46 100644 --- a/google-cloud-core/README.md +++ b/google-cloud-core/README.md @@ -19,16 +19,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-core - 0.10.0-alpha + 0.12.0-alpha ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-core:0.10.0-alpha' +compile 'com.google.cloud:google-cloud-core:0.12.0-alpha' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-core" % "0.10.0-alpha" +libraryDependencies += "com.google.cloud" % "google-cloud-core" % "0.12.0-alpha" ``` Troubleshooting diff --git a/google-cloud-core/pom.xml b/google-cloud-core/pom.xml index d0ea8bec137b..332beece16df 100644 --- a/google-cloud-core/pom.xml +++ b/google-cloud-core/pom.xml @@ -11,7 +11,7 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-core diff --git a/google-cloud-core/src/main/java/com/google/cloud/GcpLaunchStage.java b/google-cloud-core/src/main/java/com/google/cloud/GcpLaunchStage.java new file mode 100644 index 000000000000..af4b951f34b1 --- /dev/null +++ b/google-cloud-core/src/main/java/com/google/cloud/GcpLaunchStage.java @@ -0,0 +1,74 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * A qualifier indicating what level of access and support can be expected of a particular Google + * Cloud Platform feature. The "GeneralAvailability" qualifier is not provided since the vast + * majority of features are in this category. Note that features may be in a later launch stage + * than the client library annotation indicates. + * + *

    See more at the Launch Stages Documentation. + */ +public class GcpLaunchStage { + + /** + * Early Access features are limited to a closed group of testers. To use these features, you must + * sign up in advance and sign a Trusted Tester agreement (which includes confidentiality + * provisions). These features may be unstable, changed in backward-incompatible ways, and are not + * guaranteed to be released. + */ + @Retention(RetentionPolicy.RUNTIME) + public @interface EarlyAccess {} + + /** + * Alpha is a limited availability test for releases before they are cleared for widespread use. + * By Alpha, all significant design issues are resolved and we are in the process of verifying + * functionality. Alpha customers need to apply for access, agree to applicable terms, and have + * their projects whitelisted. Alpha releases don’t have to be feature complete, no SLAs are + * provided, and there are no technical support obligations, but they will be far enough along + * that customers can actually use them in test environments or for limited-use tests -- just like + * they would in normal production cases. + */ + @Retention(RetentionPolicy.RUNTIME) + public @interface Alpha {} + + /** + * Beta is the point at which we are ready to open a release for any customer to use. There are no + * SLA or technical support obligations in a Beta release, and charges may be waived in some + * cases. Products will be complete from a feature perspective, but may have some open outstanding + * issues. Beta releases are suitable for limited production use cases. + */ + @Retention(RetentionPolicy.RUNTIME) + public @interface Beta {} + + /** + * Deprecated features are scheduled to be shut down and removed. For more information, see the + * “Deprecation Policy” section of our Terms of Service + * and the Google Cloud Platform Subject to the Deprecation Policy + * documentation. + */ + @Retention(RetentionPolicy.RUNTIME) + public @interface Deprecated {} + + private GcpLaunchStage() { + // Intentionally left blank. + } +} diff --git a/google-cloud-core/src/main/java/com/google/cloud/GrpcTransportOptions.java b/google-cloud-core/src/main/java/com/google/cloud/GrpcTransportOptions.java index 0295b00972c9..f27ace8b01b3 100644 --- a/google-cloud-core/src/main/java/com/google/cloud/GrpcTransportOptions.java +++ b/google-cloud-core/src/main/java/com/google/cloud/GrpcTransportOptions.java @@ -210,23 +210,21 @@ public UnaryCallSettings.Builder getApiCallSettings(RetrySettings retrySettings) } /** - * Returns a channel provider. + * Returns a channel provider from the given default provider. */ - public static ChannelProvider getChannelProvider( - ServiceOptions serviceOptions) { - HostAndPort hostAndPort = HostAndPort.fromString(serviceOptions.getHost()); - InstantiatingChannelProvider.Builder builder = InstantiatingChannelProvider.newBuilder() - .setServiceAddress(hostAndPort.getHostText()) - .setPort(hostAndPort.getPort()) - .setClientLibHeader(serviceOptions.getGoogApiClientLibName(), - firstNonNull(serviceOptions.getLibraryVersion(), "")); + public static ChannelProvider setUpChannelProvider( + InstantiatingChannelProvider.Builder providerBuilder, ServiceOptions serviceOptions) { + providerBuilder.setEndpoint(serviceOptions.getHost()) + .setClientLibHeader(ServiceOptions.getGoogApiClientLibName(), + firstNonNull(ServiceOptions.getLibraryVersion(), "")); Credentials scopedCredentials = serviceOptions.getScopedCredentials(); if (scopedCredentials != null && scopedCredentials != NoCredentials.getInstance()) { - builder.setCredentialsProvider(FixedCredentialsProvider.create(scopedCredentials)); + providerBuilder.setCredentialsProvider(FixedCredentialsProvider.create(scopedCredentials)); } - return builder.build(); + return providerBuilder.build(); } + /** * Returns the timeout for the initial RPC, in milliseconds. Subsequent calls will use this value * adjusted according to {@link #getTimeoutMultiplier()}. Default value is 20000. diff --git a/google-cloud-core/src/main/java/com/google/cloud/HttpTransportOptions.java b/google-cloud-core/src/main/java/com/google/cloud/HttpTransportOptions.java index 970ca555fea6..9308704eb116 100644 --- a/google-cloud-core/src/main/java/com/google/cloud/HttpTransportOptions.java +++ b/google-cloud-core/src/main/java/com/google/cloud/HttpTransportOptions.java @@ -50,8 +50,9 @@ public static class DefaultHttpTransportFactory implements HttpTransportFactory @Override public HttpTransport create() { - // Consider App Engine - if (ServiceOptions.getAppEngineAppId() != null) { + // Consider App Engine Standard + if (System.getProperty("com.google.appengine.runtime.version") != null + && System.getenv("GAE_SERVICE") == null) { try { return new UrlFetchTransport(); } catch (Exception ignore) { diff --git a/google-cloud-core/src/main/java/com/google/cloud/Policy.java b/google-cloud-core/src/main/java/com/google/cloud/Policy.java index c8fc044086ea..0de5cdc9652c 100644 --- a/google-cloud-core/src/main/java/com/google/cloud/Policy.java +++ b/google-cloud-core/src/main/java/com/google/cloud/Policy.java @@ -202,7 +202,6 @@ public final Builder removeIdentity(Role role, Identity first, Identity... other return this; } - /** * Sets the policy's etag. * @@ -214,7 +213,7 @@ public final Builder removeIdentity(Role role, Identity first, Identity... other * applied to the same version of the policy. If no etag is provided in the call to * setIamPolicy, then the existing policy is overwritten blindly. */ - protected final Builder setEtag(String etag) { + public final Builder setEtag(String etag) { this.etag = etag; return this; } diff --git a/google-cloud-datastore/README.md b/google-cloud-datastore/README.md index a5257b775521..d4ef802f8442 100644 --- a/google-cloud-datastore/README.md +++ b/google-cloud-datastore/README.md @@ -22,16 +22,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-datastore - 0.10.0-beta + 0.12.0-beta ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-datastore:0.10.0-beta' +compile 'com.google.cloud:google-cloud-datastore:0.12.0-beta' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-datastore" % "0.10.0-beta" +libraryDependencies += "com.google.cloud" % "google-cloud-datastore" % "0.12.0-beta" ``` Example Application diff --git a/google-cloud-datastore/pom.xml b/google-cloud-datastore/pom.xml index 227f57035b78..6c70ce2b0778 100644 --- a/google-cloud-datastore/pom.xml +++ b/google-cloud-datastore/pom.xml @@ -12,7 +12,7 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-datastore diff --git a/google-cloud-dns/README.md b/google-cloud-dns/README.md index 74955f6faa38..43667e82bcb9 100644 --- a/google-cloud-dns/README.md +++ b/google-cloud-dns/README.md @@ -22,16 +22,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-dns - 0.10.0-alpha + 0.12.0-alpha ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-dns:0.10.0-alpha' +compile 'com.google.cloud:google-cloud-dns:0.12.0-alpha' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-dns" % "0.10.0-alpha" +libraryDependencies += "com.google.cloud" % "google-cloud-dns" % "0.12.0-alpha" ``` Example Application diff --git a/google-cloud-dns/pom.xml b/google-cloud-dns/pom.xml index c41bcb25883a..523b1ccb25da 100644 --- a/google-cloud-dns/pom.xml +++ b/google-cloud-dns/pom.xml @@ -13,7 +13,7 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-dns diff --git a/google-cloud-errorreporting/pom.xml b/google-cloud-errorreporting/pom.xml index ea8a101eb06e..45ee768073d2 100644 --- a/google-cloud-errorreporting/pom.xml +++ b/google-cloud-errorreporting/pom.xml @@ -11,10 +11,11 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-errorreporting + ${project.version} @@ -87,6 +88,22 @@ + + org.codehaus.mojo + properties-maven-plugin + 1.0-alpha-2 + + + generate-resources + + write-project-properties + + + ${project.build.outputDirectory}/project.properties + + + + org.codehaus.mojo build-helper-maven-plugin diff --git a/google-cloud-errorreporting/src/main/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorGroupServiceSettings.java b/google-cloud-errorreporting/src/main/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorGroupServiceSettings.java index bcfd793f9908..ddb60e977e77 100644 --- a/google-cloud-errorreporting/src/main/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorGroupServiceSettings.java +++ b/google-cloud-errorreporting/src/main/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorGroupServiceSettings.java @@ -16,6 +16,7 @@ package com.google.cloud.errorreporting.spi.v1beta1; import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; import com.google.api.gax.core.RetrySettings; import com.google.api.gax.grpc.ChannelProvider; import com.google.api.gax.grpc.ClientSettings; @@ -69,12 +70,6 @@ @Generated("by GAPIC v0.0.5") @ExperimentalApi public class ErrorGroupServiceSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "clouderrorreporting.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder().add("https://www.googleapis.com/auth/cloud-platform").build(); @@ -82,6 +77,11 @@ public class ErrorGroupServiceSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final SimpleCallSettings getGroupSettings; private final SimpleCallSettings updateGroupSettings; @@ -100,14 +100,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "clouderrorreporting.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -123,15 +118,19 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = ErrorGroupServiceSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty( + ErrorGroupServiceSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ diff --git a/google-cloud-errorreporting/src/main/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorStatsServiceSettings.java b/google-cloud-errorreporting/src/main/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorStatsServiceSettings.java index 7029ae4619de..694db283b3d2 100644 --- a/google-cloud-errorreporting/src/main/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorStatsServiceSettings.java +++ b/google-cloud-errorreporting/src/main/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorStatsServiceSettings.java @@ -19,6 +19,7 @@ import static com.google.cloud.errorreporting.spi.v1beta1.PagedResponseWrappers.ListGroupStatsPagedResponse; import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; import com.google.api.gax.core.RetrySettings; import com.google.api.gax.grpc.CallContext; import com.google.api.gax.grpc.ChannelProvider; @@ -82,12 +83,6 @@ @Generated("by GAPIC v0.0.5") @ExperimentalApi public class ErrorStatsServiceSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "clouderrorreporting.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder().add("https://www.googleapis.com/auth/cloud-platform").build(); @@ -95,6 +90,11 @@ public class ErrorStatsServiceSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final PagedCallSettings< ListGroupStatsRequest, ListGroupStatsResponse, ListGroupStatsPagedResponse> listGroupStatsSettings; @@ -125,14 +125,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "clouderrorreporting.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -148,15 +143,19 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = ErrorStatsServiceSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty( + ErrorStatsServiceSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ diff --git a/google-cloud-errorreporting/src/main/java/com/google/cloud/errorreporting/spi/v1beta1/ReportErrorsServiceSettings.java b/google-cloud-errorreporting/src/main/java/com/google/cloud/errorreporting/spi/v1beta1/ReportErrorsServiceSettings.java index 4bd9fd99c30b..372ce78d03ff 100644 --- a/google-cloud-errorreporting/src/main/java/com/google/cloud/errorreporting/spi/v1beta1/ReportErrorsServiceSettings.java +++ b/google-cloud-errorreporting/src/main/java/com/google/cloud/errorreporting/spi/v1beta1/ReportErrorsServiceSettings.java @@ -16,6 +16,7 @@ package com.google.cloud.errorreporting.spi.v1beta1; import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; import com.google.api.gax.core.RetrySettings; import com.google.api.gax.grpc.ChannelProvider; import com.google.api.gax.grpc.ClientSettings; @@ -68,12 +69,6 @@ @Generated("by GAPIC v0.0.5") @ExperimentalApi public class ReportErrorsServiceSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "clouderrorreporting.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder().add("https://www.googleapis.com/auth/cloud-platform").build(); @@ -81,6 +76,11 @@ public class ReportErrorsServiceSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final SimpleCallSettings reportErrorEventSettings; @@ -95,14 +95,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "clouderrorreporting.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -118,16 +113,19 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = - ReportErrorsServiceSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty( + ReportErrorsServiceSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ diff --git a/google-cloud-errorreporting/src/test/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorGroupServiceClientTest.java b/google-cloud-errorreporting/src/test/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorGroupServiceClientTest.java index f36aefdcb516..dc0f7a6d6d5f 100644 --- a/google-cloud-errorreporting/src/test/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorGroupServiceClientTest.java +++ b/google-cloud-errorreporting/src/test/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorGroupServiceClientTest.java @@ -100,7 +100,7 @@ public void getGroupTest() { @Test @SuppressWarnings("all") public void getGroupExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockErrorGroupService.addException(exception); try { @@ -109,7 +109,7 @@ public void getGroupExceptionTest() throws Exception { client.getGroup(groupName); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -137,7 +137,7 @@ public void updateGroupTest() { @Test @SuppressWarnings("all") public void updateGroupExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockErrorGroupService.addException(exception); try { @@ -146,7 +146,7 @@ public void updateGroupExceptionTest() throws Exception { client.updateGroup(group); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } } diff --git a/google-cloud-errorreporting/src/test/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorStatsServiceClientTest.java b/google-cloud-errorreporting/src/test/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorStatsServiceClientTest.java index 5d99dedf092f..76b3f535a433 100644 --- a/google-cloud-errorreporting/src/test/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorStatsServiceClientTest.java +++ b/google-cloud-errorreporting/src/test/java/com/google/cloud/errorreporting/spi/v1beta1/ErrorStatsServiceClientTest.java @@ -119,7 +119,7 @@ public void listGroupStatsTest() { @Test @SuppressWarnings("all") public void listGroupStatsExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockErrorStatsService.addException(exception); try { @@ -129,7 +129,7 @@ public void listGroupStatsExceptionTest() throws Exception { client.listGroupStats(projectName, timeRange); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -166,7 +166,7 @@ public void listEventsTest() { @Test @SuppressWarnings("all") public void listEventsExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockErrorStatsService.addException(exception); try { @@ -176,7 +176,7 @@ public void listEventsExceptionTest() throws Exception { client.listEvents(projectName, groupId); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -201,7 +201,7 @@ public void deleteEventsTest() { @Test @SuppressWarnings("all") public void deleteEventsExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockErrorStatsService.addException(exception); try { @@ -210,7 +210,7 @@ public void deleteEventsExceptionTest() throws Exception { client.deleteEvents(projectName); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } } diff --git a/google-cloud-errorreporting/src/test/java/com/google/cloud/errorreporting/spi/v1beta1/ReportErrorsServiceClientTest.java b/google-cloud-errorreporting/src/test/java/com/google/cloud/errorreporting/spi/v1beta1/ReportErrorsServiceClientTest.java index edf2da22c398..93a5d3524b58 100644 --- a/google-cloud-errorreporting/src/test/java/com/google/cloud/errorreporting/spi/v1beta1/ReportErrorsServiceClientTest.java +++ b/google-cloud-errorreporting/src/test/java/com/google/cloud/errorreporting/spi/v1beta1/ReportErrorsServiceClientTest.java @@ -99,7 +99,7 @@ public void reportErrorEventTest() { @Test @SuppressWarnings("all") public void reportErrorEventExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockReportErrorsService.addException(exception); try { @@ -109,7 +109,7 @@ public void reportErrorEventExceptionTest() throws Exception { client.reportErrorEvent(projectName, event); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } } diff --git a/google-cloud-examples/README.md b/google-cloud-examples/README.md index 1dbbc9ce1417..67a1fe10fdb8 100644 --- a/google-cloud-examples/README.md +++ b/google-cloud-examples/README.md @@ -19,16 +19,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-examples - 0.10.0-alpha + 0.12.0-alpha ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-examples:0.10.0-alpha' +compile 'com.google.cloud:google-cloud-examples:0.12.0-alpha' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-examples" % "0.10.0-alpha" +libraryDependencies += "com.google.cloud" % "google-cloud-examples" % "0.12.0-alpha" ``` To run examples from your command line: @@ -128,7 +128,6 @@ To run examples from your command line: target/appassembler/bin/PubSubExample create topic test-topic target/appassembler/bin/PubSubExample create subscription test-topic test-subscription target/appassembler/bin/PubSubExample publish test-topic message1 message2 - target/appassembler/bin/PubSubExample pull sync test-subscription 2 ``` * Here's an example run of `ResourceManagerExample`. @@ -170,7 +169,7 @@ To run examples from your command line: * Here's an example run of `TranslateExample`. - Before running the example, go to the [Google Developers Console][developers-console] to ensure that "Google Translate API" is enabled and that you have a valid API key. + Before running the example, go to the [Google Developers Console][developers-console] to ensure that "Google Translation API" is enabled and that you have a valid API key. ``` target/appassembler/bin/TranslateExample languages target/appassembler/bin/TranslateExample detect Hello,\ World! diff --git a/google-cloud-examples/pom.xml b/google-cloud-examples/pom.xml index cf6d14d4e6fc..e4249ecaff4c 100644 --- a/google-cloud-examples/pom.xml +++ b/google-cloud-examples/pom.xml @@ -11,7 +11,7 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-examples diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/PubSubExample.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/PubSubExample.java new file mode 100644 index 000000000000..826ee4fd3f4b --- /dev/null +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/PubSubExample.java @@ -0,0 +1,840 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.examples.pubsub; + +import com.google.api.gax.core.ApiFuture; +import com.google.api.gax.core.ApiFutureCallback; +import com.google.api.gax.core.ApiFutures; +import com.google.cloud.Identity; +import com.google.cloud.Role; +import com.google.cloud.ServiceOptions; +import com.google.cloud.pubsub.spi.v1.*; +import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.iam.v1.Binding; +import com.google.iam.v1.Policy; +import com.google.iam.v1.TestIamPermissionsResponse; +import com.google.protobuf.ByteString; +import com.google.pubsub.v1.*; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * An example of using Google Pub/Sub. + * + *

    This example demonstrates a simple/typical Pub/Sub usage. + * + *

    See the + * + * README for compilation instructions. Run this code with + *

    {@code target/appassembler/bin/PubSubExample
    + *  -Dexec.args="[]
    + *  pull async  ?
    + *  pull sync  
    + *  publish  +
    + *  replace-push-config  ?
    + *  create topic 
    + *  create subscription   ?
    + *  list subscriptions ?
    + *  list topics
    + *  delete topic 
    + *  delete subscription 
    + *  info topic 
    + *  info subscription 
    + *  get-policy topic 
    + *  get-policy subscription 
    + *  add-identity topic   
    + *  add-identity subscription   
    + *  test-permissions topic  +
    + *  test-permissions subscription  +"}
    + * + *

    The first parameter is an optional {@code project_id} (logged-in project will be used if not + * supplied). Second parameter is a Pub/Sub operation and can be used to demonstrate its usage. For + * operations that apply to more than one entity (`list`, `create`, `info` and `delete`) the third + * parameter specifies the entity. `pull` operation also takes a third parameter to specify whether + * pulling should be synchronous or asynchronous. + */ +public class PubSubExample { + + private static final Map CREATE_ACTIONS = new HashMap<>(); + private static final Map INFO_ACTIONS = new HashMap<>(); + private static final Map LIST_ACTIONS = new HashMap<>(); + private static final Map DELETE_ACTIONS = new HashMap<>(); + private static final Map PULL_ACTIONS = new HashMap<>(); + private static final Map GET_IAM_ACTIONS = new HashMap<>(); + private static final Map REPLACE_IAM_ACTIONS = new HashMap<>(); + private static final Map TEST_IAM_ACTIONS = new HashMap<>(); + private static final Map ACTIONS = new HashMap<>(); + + private static String projectId; + + private abstract static class PubSubAction { + + abstract void run(T arg) throws Exception; + + abstract T parse(String... args) throws Exception; + + protected String params() { + return ""; + } + } + + private static class Tuple { + + private final X x; + private final Y y; + + private Tuple(X x, Y y) { + this.x = x; + this.y = y; + } + + public static Tuple of(X x, Y y) { + return new Tuple<>(x, y); + } + + X x() { + return x; + } + + Y y() { + return y; + } + } + + private static class ParentAction extends PubSubAction> { + + private final Map subActions; + + ParentAction(Map subActions) { + this.subActions = ImmutableMap.copyOf(subActions); + } + + @Override + @SuppressWarnings("unchecked") + void run(Tuple subaction) throws Exception { + subaction.x().run(subaction.y()); + } + + @Override + Tuple parse(String... args) throws Exception { + if (args.length >= 1) { + PubSubAction action = subActions.get(args[0]); + if (action != null) { + Object actionArguments = action.parse(Arrays.copyOfRange(args, 1, args.length)); + return Tuple.of(action, actionArguments); + } else { + throw new IllegalArgumentException("Unrecognized entity '" + args[0] + "'."); + } + } + throw new IllegalArgumentException("Missing required entity."); + } + + @Override + public String params() { + StringBuilder builder = new StringBuilder(); + for (Map.Entry entry : subActions.entrySet()) { + builder.append('\n').append(entry.getKey()); + String param = entry.getValue().params(); + if (param != null && !param.isEmpty()) { + builder.append(' ').append(param); + } + } + return builder.toString(); + } + } + + private abstract static class NoArgsAction extends PubSubAction { + @Override + Void parse(String... args) throws Exception { + if (args.length == 0) { + return null; + } + throw new IllegalArgumentException("This action takes no arguments."); + } + } + + /** + * This class demonstrates how to list Pub/Sub topics. + * + * @see List + * topics in your project + */ + private static class ListTopicsAction extends NoArgsAction { + @Override + public void run(Void arg) throws Exception { + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + ListTopicsRequest listTopicsRequest = + ListTopicsRequest.newBuilder() + .setProjectWithProjectName(ProjectName.create(projectId)) + .build(); + PagedResponseWrappers.ListTopicsPagedResponse response = topicAdminClient.listTopics(listTopicsRequest); + Iterable topics = response.iterateAllElements(); + for (Topic topic : topics) { + System.out.println(topic.getName()); + } + } + } + } + + private abstract static class TopicAction extends PubSubAction { + @Override + String parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return args[0]; + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required topic name."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + /** + * This class demonstrates how to retrieve information on a Pub/Sub topic. + */ + private static class TopicRetrievalAction extends TopicAction { + @Override + public void run(String topicId) throws Exception { + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + Topic topic = topicAdminClient.getTopic(TopicName.create(projectId, topicId)); + System.out.printf("Topic : %s%n", topic); + } + } + } + + /** + * This class demonstrates how to create a Pub/Sub topic. + * + * @see Create a topic + */ + private static class CreateTopicAction extends TopicAction { + @Override + public void run(String topicId) throws Exception { + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + TopicName topicName = TopicName.create(projectId, topicId); + Topic topic = topicAdminClient.createTopic(topicName); + System.out.printf("Created topic %s%n", topic.getName()); + } + } + } + + /** + * This class demonstrates how to delete a Pub/Sub topic. + * + * @see Delete a topic + */ + private static class DeleteTopicAction extends TopicAction { + @Override + public void run(String topicId) throws Exception { + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + topicAdminClient.deleteTopic(TopicName.create(projectId, topicId)); + System.out.printf("Deleted topic %s%n", topicId); + } + } + } + + /** + * This class demonstrates how to list Pub/Sub subscriptions. + * + * @see List subscriptions + */ + private static class ListSubscriptionsAction extends PubSubAction { + @Override + public void run(String topic) throws Exception { + if (topic == null) { + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { + PagedResponseWrappers.ListSubscriptionsPagedResponse response = + subscriptionAdminClient.listSubscriptions(ProjectName.create(projectId)); + Iterable subscriptions = response.iterateAllElements(); + for (Subscription subscription : subscriptions) { + System.out.println(subscription.getName()); + } + } + } else { + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + PagedResponseWrappers.ListTopicSubscriptionsPagedResponse response = + topicAdminClient.listTopicSubscriptions(TopicName.create(projectId, topic)); + Iterable subscriptionNames = response.iterateAllElements(); + for (String subscriptionName : subscriptionNames) { + System.out.println(subscriptionName); + } + } + } + } + + @Override + String parse(String... args) throws Exception { + if (args.length == 1) { + return args[0]; + } else if (args.length == 0) { + return null; + } else { + throw new IllegalArgumentException("Too many arguments."); + } + } + + @Override + public String params() { + return "?"; + } + } + + /** + * This class demonstrates how to publish messages to a Pub/Sub topic. + * + * @see Publish + * messages to a topic + */ + private static class PublishMessagesAction extends PubSubAction>> { + @Override + public void run(Tuple> params) throws Exception { + String topic = params.x(); + TopicName topicName = TopicName.create(projectId, topic); + Publisher publisher = Publisher.defaultBuilder(topicName).build(); + List messages = params.y(); + for (PubsubMessage message : messages) { + ApiFuture messageIdFuture = publisher.publish(message); + ApiFutures.addCallback(messageIdFuture, new ApiFutureCallback() { + public void onSuccess(String messageId) { + System.out.println("published with message id: " + messageId); + } + + public void onFailure(Throwable t) { + System.out.println("failed to publish: " + t); + } + }); + } + System.out.printf("Published %d messages to topic %s%n", messages.size(), topic); + } + + @Override + Tuple> parse(String... args) throws Exception { + if (args.length < 2) { + throw new IllegalArgumentException("Missing required topic and messages"); + } + String topic = args[0]; + List messages = new ArrayList<>(); + for (String payload : Arrays.copyOfRange(args, 1, args.length)) { + ByteString data = ByteString.copyFromUtf8(payload); + PubsubMessage pubsubMessage = PubsubMessage.newBuilder().setData(data).build(); + messages.add(pubsubMessage); + } + return Tuple.of(topic, messages); + } + + @Override + public String params() { + return " +"; + } + } + + private abstract static class SubscriptionAction extends PubSubAction { + @Override + String parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return args[0]; + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required subscription name."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + /** + * This class demonstrates how to retrieve a Pub/Sub subscription. + */ + private static class SubscriptionInfoAction extends SubscriptionAction { + @Override + public void run(String subscriptionId) throws Exception { + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { + Subscription subscription = subscriptionAdminClient.getSubscription( + SubscriptionName.create(projectId, subscriptionId)); + System.out.printf("Subscription info: %s%n", subscription.getName()); + } + } + } + + /** + * This class demonstrates how to create a Pub/Sub subscription. + * + * @see Create a subscription + */ + private static class CreateSubscriptionAction extends + PubSubAction, PushConfig>> { + @Override + public void run(Tuple, PushConfig> subscriptionParams) throws Exception { + Tuple nameTuple = subscriptionParams.x(); + TopicName topicName = nameTuple.x(); + SubscriptionName subscriptionName = nameTuple.y(); + PushConfig pushConfig = subscriptionParams.y(); + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { + Subscription subscription = subscriptionAdminClient.createSubscription( + subscriptionName, topicName, pushConfig, 60); + System.out.printf("Created subscription %s%n", subscription.getName()); + } + } + + @Override + Tuple, PushConfig> parse(String... args) throws Exception { + String message; + if (args.length > 3) { + message = "Too many arguments."; + } else if (args.length < 2) { + message = "Missing required topic or subscription name"; + } else { + TopicName topicName = TopicName.create(projectId, args[0]); + SubscriptionName subscriptionName = SubscriptionName.create(projectId, args[1]); + PushConfig pushConfig = PushConfig.getDefaultInstance(); + if (args.length == 3) { + pushConfig = PushConfig.newBuilder().setPushEndpoint(args[2]).build(); + } + return new Tuple<>(new Tuple<>(topicName, subscriptionName), pushConfig); + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return " ?"; + } + } + + /** + * This class demonstrates how to delete a Pub/Sub subscription. + */ + private static class DeleteSubscriptionAction extends SubscriptionAction { + @Override + public void run(String subscriptionId) throws Exception { + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { + subscriptionAdminClient.deleteSubscription(SubscriptionName.create(projectId, subscriptionId)); + System.out.printf("Deleted subscription %s%n", subscriptionId); + } + } + } + + /** + * This class demonstrates how to modify the push configuration for a Pub/Sub subscription. + * + * @see + * Switching between push and pull delivery + */ + private static class ReplacePushConfigAction extends + PubSubAction> { + @Override + public void run(Tuple params) throws Exception { + SubscriptionName subscriptionName = params.x(); + PushConfig pushConfig = params.y(); + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { + subscriptionAdminClient.modifyPushConfig(subscriptionName, pushConfig); + } + System.out.printf("Set push config %s for subscription %s%n", pushConfig, subscriptionName); + } + + @Override + Tuple parse(String... args) throws Exception { + String message; + if (args.length > 2) { + message = "Too many arguments."; + } else if (args.length < 1) { + message = "Missing required subscription name"; + } else { + SubscriptionName subscriptionName = SubscriptionName.create(projectId, args[0]); + PushConfig pushConfig = null; + if (args.length == 2) { + pushConfig = PushConfig.newBuilder().setPushEndpoint(args[1]).build(); + } + return Tuple.of(subscriptionName, pushConfig); + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return " ?"; + } + } + + /** + * This class demonstrates how to asynchronously pull messages from a Pub/Sub pull subscription. + * Messages are pulled until a timeout is reached. + * + * @see Receiving + * pull messages + */ + private static class PullAsyncAction extends PubSubAction> { + @Override + public void run(Tuple params) throws Exception { + final AtomicInteger messageCount = new AtomicInteger(); + MessageReceiver receiver = + new MessageReceiver() { + @Override + public void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) { + messageCount.incrementAndGet(); + consumer.accept(AckReply.ACK); + } + }; + SubscriptionName subscriptionName = params.x(); + Subscriber subscriber = null; + try { + subscriber = Subscriber.defaultBuilder(subscriptionName, receiver).build(); + subscriber.addListener( + new Subscriber.Listener() { + @Override + public void failed(Subscriber.State from, Throwable failure) { + // Handle failure. + // This is called when the Subscriber encountered a fatal error and is shutting down. + System.err.println(failure); + } + }, + MoreExecutors.directExecutor()); + subscriber.startAsync().awaitRunning(); + Thread.sleep(params.y()); + } finally { + if (subscriber != null) { + subscriber.stopAsync(); + } + } + System.out.printf("Pulled %d messages from subscription %s%n", messageCount.get(), subscriptionName); + } + + @Override + Tuple parse(String... args) throws Exception { + String message; + if (args.length > 2) { + message = "Too many arguments."; + } else if (args.length < 1) { + message = "Missing required subscription name"; + } else { + String subscriptionId = args[0]; + long timeout = 60_000; + if (args.length == 2) { + timeout = Long.parseLong(args[1]); + } + return Tuple.of(SubscriptionName.create(projectId, subscriptionId), timeout); + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return " ?"; + } + } + + private abstract static class GetPolicyAction extends PubSubAction { + @Override + String parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return args[0]; + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required resource name"; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + /** + * This class demonstrates how to get the IAM policy of a topic. + * + * @see Access Control + */ + private static class GetTopicPolicyAction extends GetPolicyAction { + @Override + public void run(String topicId) throws Exception { + TopicName topicName = TopicName.create(projectId, topicId); + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + Policy policy = topicAdminClient.getIamPolicy(topicName.toString()); + System.out.printf("Policy for topic %s%n", topicId); + System.out.println(policy); + } + } + } + + /** + * This class demonstrates how to get the IAM policy of a subscription. + * + * @see Access Control + */ + private static class GetSubscriptionPolicyAction extends GetPolicyAction { + @Override + public void run(String subscription) throws Exception { + SubscriptionName subscriptionName = SubscriptionName.create(projectId, subscription); + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { + Policy policy = subscriptionAdminClient.getIamPolicy(subscriptionName.toString()); + System.out.printf("Policy for subscription %s%n", subscription); + System.out.println(policy); + } + } + } + + private abstract static class AddIdentityAction extends PubSubAction>> { + @Override + Tuple> parse(String... args) throws Exception { + String message; + if (args.length == 3) { + String resourceName = args[0]; + Role role = Role.of(args[1]); + Identity identity = Identity.valueOf(args[2]); + return Tuple.of(resourceName, Tuple.of(role, identity)); + } else if (args.length > 2) { + message = "Too many arguments."; + } else { + message = "Missing required resource name, role and identity"; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return " "; + } + } + + + /** + * This class demonstrates how to add an identity to a certain role in a topic's IAM policy. + * + * @see Access Control + */ + private static class AddIdentityTopicAction extends AddIdentityAction { + @Override + public void run(Tuple> param) throws Exception { + TopicName topicName = TopicName.create(projectId, param.x()); + Tuple roleAndIdentity = param.y(); + Role role = roleAndIdentity.x(); + Identity identity = roleAndIdentity.y(); + Binding binding = + Binding.newBuilder() + .setRole(role.toString()) + .addMembers(identity.toString()) + .build(); + //Update policy + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + Policy policy = topicAdminClient.getIamPolicy(topicName.toString()); + //Update policy + Policy updatedPolicy = policy.toBuilder().addBindings(binding).build(); + updatedPolicy = topicAdminClient.setIamPolicy(topicName.toString(), updatedPolicy); + System.out.printf("Added role %s to identity %s for topic %s%n", role, identity, topicName); + System.out.println(updatedPolicy); + } + } + } + + /** + * This class demonstrates how to add an identity to a certain role in a subscription's IAM + * policy. + * + * @see Access Control + */ + private static class AddIdentitySubscriptionAction extends AddIdentityAction { + @Override + public void run(Tuple> param) throws Exception { + SubscriptionName subscriptionName = SubscriptionName.create(projectId, param.x()); + // Create a role => identity binding + Role role = param.y().x(); + Identity identity = param.y().y(); + Binding binding = + Binding.newBuilder() + .setRole(role.toString()) + .addMembers(identity.toString()) + .build(); + + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { + Policy policy = subscriptionAdminClient.getIamPolicy(subscriptionName.toString()); + //Update policy + Policy updatedPolicy = policy.toBuilder().addBindings(binding).build(); + + updatedPolicy = subscriptionAdminClient.setIamPolicy(subscriptionName.toString(), updatedPolicy); + System.out.printf("Added role %s to identity %s for subscription %s%n", role, identity, + subscriptionName); + System.out.println(updatedPolicy); + } + } + } + + private abstract static class TestPermissionsAction extends PubSubAction>> { + @Override + Tuple> parse(String... args) throws Exception { + if (args.length >= 2) { + String resourceName = args[0]; + return Tuple.of(resourceName, Arrays.asList(Arrays.copyOfRange(args, 1, args.length))); + } + throw new IllegalArgumentException("Missing required resource name and permissions"); + } + + @Override + public String params() { + return " +"; + } + } + + /** + * This class demonstrates how to test whether the caller has the provided permissions on a topic. + * + * @see Access Control + */ + private static class TestTopicPermissionsAction extends TestPermissionsAction { + @Override + public void run(Tuple> param) throws Exception { + TopicName topicName = TopicName.create(projectId, param.x()); + List permissions = param.y(); + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + TestIamPermissionsResponse response = + topicAdminClient.testIamPermissions(topicName.toString(), permissions); + System.out.println("Topic permissions test : "); + Set actualPermissions = new HashSet<>(); + actualPermissions.addAll(response.getPermissionsList()); + for (String permission : permissions) { + System.out.println(permission + " : " + actualPermissions.contains(permission)); + } + } + } + } + + /** + * This class demonstrates how to test whether the caller has the provided permissions on a + * subscription. + * + * @see Access Control + */ + private static class TestSubscriptionPermissionsAction extends TestPermissionsAction { + @Override + public void run(Tuple> param) throws Exception { + SubscriptionName subscriptionName = SubscriptionName.create(projectId, param.x()); + List permissions = param.y(); + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { + TestIamPermissionsResponse response = + subscriptionAdminClient.testIamPermissions(subscriptionName.toString(), + permissions); + System.out.println("Subscription permissions test : "); + Set actualPermissions = new HashSet<>(); + actualPermissions.addAll(response.getPermissionsList()); + for (String permission : permissions) { + System.out.println(permission + " : " + actualPermissions.contains(permission)); + } + } + } + } + + static { + CREATE_ACTIONS.put("topic", new CreateTopicAction()); + CREATE_ACTIONS.put("subscription", new CreateSubscriptionAction()); + INFO_ACTIONS.put("topic", new TopicRetrievalAction()); + INFO_ACTIONS.put("subscription", new SubscriptionInfoAction()); + LIST_ACTIONS.put("topics", new ListTopicsAction()); + LIST_ACTIONS.put("subscriptions", new ListSubscriptionsAction()); + DELETE_ACTIONS.put("topic", new DeleteTopicAction()); + DELETE_ACTIONS.put("subscription", new DeleteSubscriptionAction()); + PULL_ACTIONS.put("async", new PullAsyncAction()); + GET_IAM_ACTIONS.put("topic", new GetTopicPolicyAction()); + GET_IAM_ACTIONS.put("subscription", new GetSubscriptionPolicyAction()); + REPLACE_IAM_ACTIONS.put("topic", new AddIdentityTopicAction()); + REPLACE_IAM_ACTIONS.put("subscription", new AddIdentitySubscriptionAction()); + TEST_IAM_ACTIONS.put("topic", new TestTopicPermissionsAction()); + TEST_IAM_ACTIONS.put("subscription", new TestSubscriptionPermissionsAction()); + ACTIONS.put("create", new ParentAction(CREATE_ACTIONS)); + ACTIONS.put("info", new ParentAction(INFO_ACTIONS)); + ACTIONS.put("list", new ParentAction(LIST_ACTIONS)); + ACTIONS.put("delete", new ParentAction(DELETE_ACTIONS)); + ACTIONS.put("pull", new ParentAction(PULL_ACTIONS)); + ACTIONS.put("get-policy", new ParentAction(GET_IAM_ACTIONS)); + ACTIONS.put("add-identity", new ParentAction(REPLACE_IAM_ACTIONS)); + ACTIONS.put("test-permissions", new ParentAction(TEST_IAM_ACTIONS)); + ACTIONS.put("publish", new PublishMessagesAction()); + ACTIONS.put("replace-push-config", new ReplacePushConfigAction()); + } + + private static void printUsage() { + StringBuilder actionAndParams = new StringBuilder(); + for (Map.Entry entry : ACTIONS.entrySet()) { + actionAndParams.append("\n\t").append(entry.getKey()); + + String param = entry.getValue().params(); + if (param != null && !param.isEmpty()) { + actionAndParams.append(' ').append(param.replace("\n", "\n\t\t")); + } + } + System.out.printf("Usage: %s [] operation [entity] *%s%n", + PubSubExample.class.getSimpleName(), actionAndParams); + } + + @SuppressWarnings("unchecked") + public static void main(String... args) throws Exception { + if (args.length < 1) { + System.out.println("Missing required project id and action"); + printUsage(); + return; + } + PubSubAction action; + String actionName; + if (args.length >= 2 && !ACTIONS.containsKey(args[0])) { + actionName = args[1]; + projectId = args[0]; + action = ACTIONS.get(args[1]); + args = Arrays.copyOfRange(args, 2, args.length); + } else { + actionName = args[0]; + projectId = ServiceOptions.getDefaultProjectId(); + action = ACTIONS.get(args[0]); + args = Arrays.copyOfRange(args, 1, args.length); + } + if (action == null) { + System.out.println("Unrecognized action."); + printUsage(); + return; + } + Object arg; + try { + arg = action.parse(args); + } catch (IllegalArgumentException ex) { + System.out.printf("Invalid input for action '%s'. %s%n", actionName, ex.getMessage()); + System.out.printf("Expected: %s%n", action.params()); + return; + } catch (Exception ex) { + System.out.println("Failed to parse arguments."); + ex.printStackTrace(); + return; + } + action.run(arg); + } +} diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/CreateSubscriptionAndPullMessages.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/CreateSubscriptionAndPullMessages.java index 531de1cc7fbf..2fece107b678 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/CreateSubscriptionAndPullMessages.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/CreateSubscriptionAndPullMessages.java @@ -20,7 +20,7 @@ import com.google.cloud.pubsub.spi.v1.AckReplyConsumer; import com.google.cloud.pubsub.spi.v1.MessageReceiver; import com.google.cloud.pubsub.spi.v1.Subscriber; -import com.google.cloud.pubsub.spi.v1.SubscriberClient; +import com.google.cloud.pubsub.spi.v1.SubscriptionAdminClient; import com.google.common.util.concurrent.MoreExecutors; import com.google.pubsub.v1.PubsubMessage; import com.google.pubsub.v1.PushConfig; @@ -34,11 +34,12 @@ public class CreateSubscriptionAndPullMessages { public static void main(String... args) throws Exception { + // [START async_pull_subscription] TopicName topic = TopicName.create("test-project", "test-topic"); SubscriptionName subscription = SubscriptionName.create("test-project", "test-subscription"); - try (SubscriberClient subscriberClient = SubscriberClient.create()) { - subscriberClient.createSubscription(subscription, topic, PushConfig.getDefaultInstance(), 0); + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { + subscriptionAdminClient.createSubscription(subscription, topic, PushConfig.getDefaultInstance(), 0); } MessageReceiver receiver = @@ -51,9 +52,9 @@ public void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) { }; Subscriber subscriber = null; try { - subscriber = Subscriber.newBuilder(subscription, receiver).build(); + subscriber = Subscriber.defaultBuilder(subscription, receiver).build(); subscriber.addListener( - new Subscriber.SubscriberListener() { + new Subscriber.Listener() { @Override public void failed(Subscriber.State from, Throwable failure) { // Handle failure. This is called when the Subscriber encountered a fatal error and is shutting down. @@ -62,11 +63,13 @@ public void failed(Subscriber.State from, Throwable failure) { }, MoreExecutors.directExecutor()); subscriber.startAsync().awaitRunning(); + Thread.sleep(60000); } finally { if (subscriber != null) { subscriber.stopAsync(); } } + // [END async_pull_subscription] } } diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/CreateTopicAndPublishMessages.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/CreateTopicAndPublishMessages.java index 43c55005a7be..8021bf736c8b 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/CreateTopicAndPublishMessages.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/CreateTopicAndPublishMessages.java @@ -18,7 +18,7 @@ import com.google.api.gax.core.ApiFuture; import com.google.cloud.pubsub.spi.v1.Publisher; -import com.google.cloud.pubsub.spi.v1.PublisherClient; +import com.google.cloud.pubsub.spi.v1.TopicAdminClient; import com.google.protobuf.ByteString; import com.google.pubsub.v1.PubsubMessage; import com.google.pubsub.v1.TopicName; @@ -33,13 +33,13 @@ public class CreateTopicAndPublishMessages { public static void main(String... args) throws Exception { TopicName topic = TopicName.create("test-project", "test-topic"); - try (PublisherClient publisherClient = PublisherClient.create()) { - publisherClient.createTopic(topic); + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + topicAdminClient.createTopic(topic); } Publisher publisher = null; try { - publisher = Publisher.newBuilder(topic).build(); + publisher = Publisher.defaultBuilder(topic).build(); List messages = Arrays.asList("first message", "second message"); List> messageIds = new ArrayList<>(); for (String message : messages) { diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/PublisherSnippets.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/PublisherSnippets.java index 6f431d6277f1..39465d573149 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/PublisherSnippets.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/PublisherSnippets.java @@ -65,7 +65,7 @@ public void onFailure(Throwable t) { public static void newBuilder(String projectName, String topicName) throws Exception { // [START newBuilder] TopicName topic = TopicName.create(projectName, topicName); - Publisher publisher = Publisher.newBuilder(topic).build(); + Publisher publisher = Publisher.defaultBuilder(topic).build(); try { // ... } finally { diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/SubscriberSnippets.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/SubscriberSnippets.java index d2340d2a0834..e5c0d840399d 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/SubscriberSnippets.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/SubscriberSnippets.java @@ -53,8 +53,8 @@ public SubscriberSnippets( // [TARGET startAsync()] public void startAndWait() throws Exception { // [START startAsync] - Subscriber subscriber = Subscriber.newBuilder(subscription, receiver).build(); - subscriber.addListener(new Subscriber.SubscriberListener() { + Subscriber subscriber = Subscriber.defaultBuilder(subscription, receiver).build(); + subscriber.addListener(new Subscriber.Listener() { public void failed(Subscriber.State from, Throwable failure) { // Handle error. } diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/SubscriberClientSnippets.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/SubscriptionAdminClientSnippets.java similarity index 56% rename from google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/SubscriberClientSnippets.java rename to google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/SubscriptionAdminClientSnippets.java index bee70a1a118b..40df803b451f 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/SubscriberClientSnippets.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/SubscriptionAdminClientSnippets.java @@ -14,7 +14,7 @@ * limitations under the License. */ -/** This class contains snippets for the {@link SubscriberClient} interface. */ +/** This class contains snippets for the {@link SubscriptionAdminClient} interface. */ package com.google.cloud.examples.pubsub.snippets; @@ -22,8 +22,8 @@ import com.google.cloud.Role; import com.google.cloud.ServiceOptions; import com.google.cloud.pubsub.spi.v1.PagedResponseWrappers.ListSubscriptionsPagedResponse; -import com.google.cloud.pubsub.spi.v1.PublisherClient; -import com.google.cloud.pubsub.spi.v1.SubscriberClient; +import com.google.cloud.pubsub.spi.v1.TopicAdminClient; +import com.google.cloud.pubsub.spi.v1.SubscriptionAdminClient; import com.google.iam.v1.Binding; import com.google.iam.v1.Policy; import com.google.iam.v1.TestIamPermissionsResponse; @@ -39,12 +39,12 @@ import java.util.LinkedList; import java.util.List; -/** This class contains a number of snippets for the {@link SubscriberClient} interface. */ -public class SubscriberClientSnippets { +/** This class contains a number of snippets for the {@link SubscriptionAdminClient} interface. */ +public class SubscriptionAdminClientSnippets { private final String projectId; - public SubscriberClientSnippets() { + public SubscriptionAdminClientSnippets() { this.projectId = ServiceOptions.getDefaultProjectId(); } @@ -53,97 +53,107 @@ public String getProjectId() { } /** Example of creating a pull subscription for a topic. */ - public Subscription createSubscription(String topic, String subscriptionId) throws Exception { - try (SubscriberClient subscriberClient = SubscriberClient.create()) { - // [START createSubscription] - TopicName topicName = TopicName.create(projectId, topic); + public Subscription createSubscription(String topicId, String subscriptionId) throws Exception { + // [START createSubscription] + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { + // eg. projectId = "my-test-project", topicId = "my-test-topic" + TopicName topicName = TopicName.create(projectId, topicId); + // eg. subscriptionId = "my-test-subscription" SubscriptionName subscriptionName = SubscriptionName.create(projectId, subscriptionId); + // create a pull subscription with default acknowledgement deadline Subscription subscription = - subscriberClient.createSubscription( + subscriptionAdminClient.createSubscription( subscriptionName, topicName, PushConfig.getDefaultInstance(), 0); - // [END createSubscription] return subscription; } + // [END createSubscription] } - /** Example of pulling a maximum number of messages from a subscription. */ - public PullResponse pull(String subscriptionId) throws Exception { - try (SubscriberClient subscriberClient = SubscriberClient.create()) { - // [START pull] - SubscriptionName subscriptionName = SubscriptionName.create(projectId, subscriptionId); - PullResponse response = subscriberClient.pull(subscriptionName, true, 100); - for (ReceivedMessage message : response.getReceivedMessagesList()) { - // do something with message, then ack or nack - subscriberClient.acknowledge( - subscriptionName, Collections.singletonList(message.getAckId())); - } - // [END pull] - return response; + /** Example of creating a subscription with a push endpoint. */ + public Subscription createSubscriptionWithPushEndpoint(String topicId, String subscriptionId, String endpoint) + throws Exception { + // [START createSubscriptionWithPushEndpoint] + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { + TopicName topicName = TopicName.create(projectId, topicId); + SubscriptionName subscriptionName = + SubscriptionName.create(projectId, subscriptionId); + + // eg. endpoint = "https://my-test-project.appspot.com/push" + PushConfig pushConfig = PushConfig.newBuilder().setPushEndpoint(endpoint).build(); + + // acknowledgement deadline in seconds for the message received over the push endpoint + int ackDeadlineInSeconds = 10; + + Subscription subscription = + subscriptionAdminClient.createSubscription( + subscriptionName, topicName, pushConfig, ackDeadlineInSeconds); + return subscription; } + // [END createSubscriptionWithPushEndpoint] } /** Example of replacing the push configuration of a subscription, setting the push endpoint. */ public void replacePushConfig(String subscriptionId, String endpoint) throws Exception { - try (SubscriberClient subscriberClient = SubscriberClient.create()) { - // [START replacePushConfig] + // [START replacePushConfig] + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { SubscriptionName subscriptionName = SubscriptionName.create(projectId, subscriptionId); PushConfig pushConfig = PushConfig.newBuilder().setPushEndpoint(endpoint).build(); - subscriberClient.modifyPushConfig(subscriptionName, pushConfig); - // [END replacePushConfig] + subscriptionAdminClient.modifyPushConfig(subscriptionName, pushConfig); } + // [END replacePushConfig] } /** Example of listing subscriptions. */ public ListSubscriptionsPagedResponse listSubscriptions() throws Exception { - try (SubscriberClient subscriberClient = SubscriberClient.create()) { - // [START listSubscriptions] + // [START listSubscriptions] + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { ListSubscriptionsRequest listSubscriptionsRequest = ListSubscriptionsRequest.newBuilder() .setProjectWithProjectName(ProjectName.create(projectId)) .build(); ListSubscriptionsPagedResponse response = - subscriberClient.listSubscriptions(listSubscriptionsRequest); + subscriptionAdminClient.listSubscriptions(listSubscriptionsRequest); Iterable subscriptions = response.iterateAllElements(); for (Subscription subscription : subscriptions) { // do something with the subscription } - // [END listSubscriptions] return response; } + // [END listSubscriptions] } /** Example of deleting a subscription. */ public SubscriptionName deleteSubscription(String subscriptionId) throws Exception { - try (SubscriberClient subscriberClient = SubscriberClient.create()) { - // [START deleteSubscription] + // [START deleteSubscription] + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { SubscriptionName subscriptionName = SubscriptionName.create(projectId, subscriptionId); - subscriberClient.deleteSubscription(subscriptionName); - // [END deleteSubscription] + subscriptionAdminClient.deleteSubscription(subscriptionName); return subscriptionName; } + // [END deleteSubscription] } /** Example of getting a subscription policy. */ public Policy getSubscriptionPolicy(String subscriptionId) throws Exception { - try (SubscriberClient subscriberClient = SubscriberClient.create()) { - // [START getSubscriptionPolicy] + // [START getSubscriptionPolicy] + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { SubscriptionName subscriptionName = SubscriptionName.create(projectId, subscriptionId); - Policy policy = subscriberClient.getIamPolicy(subscriptionName.toString()); + Policy policy = subscriptionAdminClient.getIamPolicy(subscriptionName.toString()); if (policy == null) { // subscription was not found } - // [END getSubscriptionPolicy] return policy; } + // [END getSubscriptionPolicy] } /** Example of replacing a subscription policy. */ public Policy replaceSubscriptionPolicy(String subscriptionId) throws Exception { - try (SubscriberClient subscriberClient = SubscriberClient.create()) { - // [START replaceSubscriptionPolicy] + // [START replaceSubscriptionPolicy] + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { SubscriptionName subscriptionName = SubscriptionName.create(projectId, subscriptionId); - Policy policy = subscriberClient.getIamPolicy(subscriptionName.toString()); + Policy policy = subscriptionAdminClient.getIamPolicy(subscriptionName.toString()); // Create a role => members binding Binding binding = Binding.newBuilder() @@ -153,35 +163,35 @@ public Policy replaceSubscriptionPolicy(String subscriptionId) throws Exception //Update policy Policy updatedPolicy = policy.toBuilder().addBindings(binding).build(); - updatedPolicy = subscriberClient.setIamPolicy(subscriptionName.toString(), updatedPolicy); - // [END replaceSubscriptionPolicy] + updatedPolicy = subscriptionAdminClient.setIamPolicy(subscriptionName.toString(), updatedPolicy); return updatedPolicy; } + // [END replaceSubscriptionPolicy] } /** Example of testing whether the caller has the provided permissions on a subscription. */ public TestIamPermissionsResponse testSubscriptionPermissions(String subscriptionId) throws Exception { - try (PublisherClient publisherClient = PublisherClient.create()) { - // [START testSubscriptionPermissions] + // [START testSubscriptionPermissions] + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { List permissions = new LinkedList<>(); permissions.add("pubsub.subscriptions.get"); SubscriptionName subscriptionName = SubscriptionName.create(projectId, subscriptionId); TestIamPermissionsResponse testedPermissions = - publisherClient.testIamPermissions(subscriptionName.toString(), permissions); - // [END testSubscriptionPermissions] + topicAdminClient.testIamPermissions(subscriptionName.toString(), permissions); return testedPermissions; } + // [END testSubscriptionPermissions] } /** Example of getting a subscription. */ public Subscription getSubscription(String subscriptionId) throws Exception { - try (SubscriberClient subscriberClient = SubscriberClient.create()) { - // [START getSubscription] + // [START getSubscription] + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { SubscriptionName subscriptionName = SubscriptionName.create(projectId, subscriptionId); - Subscription subscription = subscriberClient.getSubscription(subscriptionName); - // [END getSubscription] + Subscription subscription = subscriptionAdminClient.getSubscription(subscriptionName); return subscription; } + // [END getSubscription] } } diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/PublisherClientSnippets.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/TopicAdminClientSnippets.java similarity index 70% rename from google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/PublisherClientSnippets.java rename to google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/TopicAdminClientSnippets.java index 9737bf4a3087..62855bd09081 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/PublisherClientSnippets.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/TopicAdminClientSnippets.java @@ -21,7 +21,7 @@ import com.google.cloud.ServiceOptions; import com.google.cloud.pubsub.spi.v1.PagedResponseWrappers.ListTopicSubscriptionsPagedResponse; import com.google.cloud.pubsub.spi.v1.PagedResponseWrappers.ListTopicsPagedResponse; -import com.google.cloud.pubsub.spi.v1.PublisherClient; +import com.google.cloud.pubsub.spi.v1.TopicAdminClient; import com.google.iam.v1.Binding; import com.google.iam.v1.Policy; import com.google.iam.v1.TestIamPermissionsResponse; @@ -33,12 +33,12 @@ import java.util.LinkedList; import java.util.List; -/** This class contains a number of snippets for the {@link PublisherClient} interface. */ -public class PublisherClientSnippets { +/** This class contains a number of snippets for the {@link TopicAdminClient} interface. */ +public class TopicAdminClientSnippets { private final String projectId; - public PublisherClientSnippets() { + public TopicAdminClientSnippets() { this.projectId = ServiceOptions.getDefaultProjectId(); } @@ -48,85 +48,85 @@ public String getProjectId() { /** Example of creating a topic. */ public Topic createTopic(String topicId) throws Exception { - try (PublisherClient publisherClient = PublisherClient.create()) { - // [START createTopic] + // [START createTopic] + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { TopicName topicName = TopicName.create(projectId, topicId); - Topic topic = publisherClient.createTopic(topicName); - // [END createTopic] + Topic topic = topicAdminClient.createTopic(topicName); return topic; } + // [END createTopic] } /** Example of listing topics. */ public ListTopicsPagedResponse listTopics() throws Exception { - try (PublisherClient publisherClient = PublisherClient.create()) { - // [START listTopics] + // [START listTopics] + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { ListTopicsRequest listTopicsRequest = ListTopicsRequest.newBuilder() .setProjectWithProjectName(ProjectName.create(projectId)) .build(); - ListTopicsPagedResponse response = publisherClient.listTopics(listTopicsRequest); + ListTopicsPagedResponse response = topicAdminClient.listTopics(listTopicsRequest); Iterable topics = response.iterateAllElements(); for (Topic topic : topics) { // do something with the topic } - // [END listTopics] return response; } + // [END listTopics] } /** Example of listing topics for a subscription. */ public ListTopicSubscriptionsPagedResponse listTopicSubscriptions(String topicId) throws Exception { - try (PublisherClient publisherClient = PublisherClient.create()) { - // [START listTopicSubscriptions] + // [START listTopicSubscriptions] + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { TopicName topicName = TopicName.create(projectId, topicId); ListTopicSubscriptionsRequest request = ListTopicSubscriptionsRequest.newBuilder() .setTopicWithTopicName(topicName) .build(); ListTopicSubscriptionsPagedResponse response = - publisherClient.listTopicSubscriptions(request); + topicAdminClient.listTopicSubscriptions(request); Iterable subscriptionNames = response.iterateAllElements(); for (String subscriptionName : subscriptionNames) { // do something with the subscription name } - // [END listTopicSubscriptions] return response; } + // [END listTopicSubscriptions] } /** Example of deleting a topic. */ public TopicName deleteTopic(String topicId) throws Exception { - try (PublisherClient publisherClient = PublisherClient.create()) { - // [START deleteTopic] + // [START deleteTopic] + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { TopicName topicName = TopicName.create(projectId, topicId); - publisherClient.deleteTopic(topicName); - // [END deleteTopic] + topicAdminClient.deleteTopic(topicName); return topicName; } + // [END deleteTopic] } /** Example of getting a topic policy. */ public Policy getTopicPolicy(String topicId) throws Exception { - try (PublisherClient publisherClient = PublisherClient.create()) { - // [START getTopicPolicy] + // [START getTopicPolicy] + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { TopicName topicName = TopicName.create(projectId, topicId); - Policy policy = publisherClient.getIamPolicy(topicName.toString()); + Policy policy = topicAdminClient.getIamPolicy(topicName.toString()); if (policy == null) { // topic iam policy was not found } - // [END getTopicPolicy] return policy; } + // [END getTopicPolicy] } /** Example of replacing a topic policy. */ public Policy replaceTopicPolicy(String topicId) throws Exception { - try (PublisherClient publisherClient = PublisherClient.create()) { - // [START replaceTopicPolicy] + // [START replaceTopicPolicy] + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { String topicName = TopicName.create(projectId, topicId).toString(); - Policy policy = publisherClient.getIamPolicy(topicName); + Policy policy = topicAdminClient.getIamPolicy(topicName); // add role -> members binding Binding binding = Binding.newBuilder() @@ -135,35 +135,35 @@ public Policy replaceTopicPolicy(String topicId) throws Exception { .build(); // create updated policy Policy updatedPolicy = Policy.newBuilder(policy).addBindings(binding).build(); - updatedPolicy = publisherClient.setIamPolicy(topicName, updatedPolicy); - // [END replaceTopicPolicy] + updatedPolicy = topicAdminClient.setIamPolicy(topicName, updatedPolicy); return updatedPolicy; } + // [END replaceTopicPolicy] } /** Example of testing whether the caller has the provided permissions on a topic. * Only viewer, editor or admin/owner can view results of pubsub.topics.get */ public TestIamPermissionsResponse testTopicPermissions(String topicId) throws Exception { - try (PublisherClient publisherClient = PublisherClient.create()) { - // [START testTopicPermissions] + // [START testTopicPermissions] + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { List permissions = new LinkedList<>(); permissions.add("pubsub.topics.get"); TopicName topicName = TopicName.create(projectId, topicId); TestIamPermissionsResponse testedPermissions = - publisherClient.testIamPermissions(topicName.toString(), permissions); - // [END testTopicPermissions] + topicAdminClient.testIamPermissions(topicName.toString(), permissions); return testedPermissions; } + // [END testTopicPermissions] } /** Example of getting a topic. */ public Topic getTopic(String topicId) throws Exception { - try (PublisherClient publisherClient = PublisherClient.create()) { - // [START getTopic] + // [START getTopic] + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { TopicName topicName = TopicName.create(projectId, topicId); - Topic topic = publisherClient.getTopic(topicName); - // [END createTopic] + Topic topic = topicAdminClient.getTopic(topicName); return topic; } + // [END getTopic] } } diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/translate/TranslateExample.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/translate/TranslateExample.java index 547689b96f80..5e3829698177 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/translate/TranslateExample.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/translate/TranslateExample.java @@ -28,9 +28,9 @@ import java.util.Map; /** - * An example of using Google Translate. + * An example of using Google Translation. * - *

    This example demonstrates a simple/typical Translate usage. + *

    This example demonstrates a simple/typical Translation usage. * *

    See the * diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/translate/snippets/DetectLanguageAndTranslate.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/translate/snippets/DetectLanguageAndTranslate.java index 5d506fe22fec..ab28d630f728 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/translate/snippets/DetectLanguageAndTranslate.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/translate/snippets/DetectLanguageAndTranslate.java @@ -29,7 +29,7 @@ import com.google.cloud.translate.Translation; /** - * A snippet for Google Translate showing how to detect the language of some text and translate + * A snippet for Google Translation showing how to detect the language of some text and translate * some other text. */ public class DetectLanguageAndTranslate { diff --git a/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/Cleanup.java b/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/Cleanup.java index c9911fd392a3..3f2c9e64be73 100644 --- a/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/Cleanup.java +++ b/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/Cleanup.java @@ -16,8 +16,8 @@ package com.google.cloud.examples.pubsub.snippets; -import com.google.cloud.pubsub.spi.v1.PublisherClient; -import com.google.cloud.pubsub.spi.v1.SubscriberClient; +import com.google.cloud.pubsub.spi.v1.TopicAdminClient; +import com.google.cloud.pubsub.spi.v1.SubscriptionAdminClient; import com.google.pubsub.v1.SubscriptionName; import com.google.pubsub.v1.TopicName; @@ -30,10 +30,10 @@ protected static void deleteTestTopicsAndSubscriptions( } private static void deleteTestTopics(String projectId, String[] testTopics) throws Exception { - try (PublisherClient publisherClient = PublisherClient.create()) { + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { for (String topicId : testTopics) { try { - publisherClient.deleteTopic(TopicName.create(projectId, topicId)); + topicAdminClient.deleteTopic(TopicName.create(projectId, topicId)); System.out.println("Topic deleted : " + topicId); } catch (Exception e) { //do nothing catch clause @@ -44,10 +44,10 @@ private static void deleteTestTopics(String projectId, String[] testTopics) thro private static void deleteTestSubscriptions(String projectId, String[] subscriptions) throws Exception { - try (SubscriberClient subscriberClient = SubscriberClient.create()) { + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { for (String subscriptionId : subscriptions) { try { - subscriberClient.deleteSubscription( + subscriptionAdminClient.deleteSubscription( SubscriptionName.create(projectId, subscriptionId)); System.out.println("Subscription deleted : " + subscriptionId); } catch (Exception e) { diff --git a/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITPubSubSnippets.java b/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITPubSubSnippets.java new file mode 100644 index 000000000000..fc329f660585 --- /dev/null +++ b/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITPubSubSnippets.java @@ -0,0 +1,127 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.examples.pubsub.snippets; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import com.google.api.gax.core.ApiFutureCallback; +import com.google.api.gax.core.ApiFutures; +import com.google.api.gax.core.SettableApiFuture; +import com.google.cloud.ServiceOptions; +import com.google.cloud.pubsub.spi.v1.Publisher; +import com.google.cloud.pubsub.spi.v1.SubscriptionAdminClient; +import com.google.cloud.pubsub.spi.v1.TopicAdminClient; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.pubsub.v1.PubsubMessage; +import com.google.pubsub.v1.PushConfig; +import com.google.pubsub.v1.SubscriptionName; +import com.google.pubsub.v1.TopicName; +import java.util.UUID; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.Timeout; + +public class ITPubSubSnippets { + + private static final String NAME_SUFFIX = UUID.randomUUID().toString(); + + @Rule public Timeout globalTimeout = Timeout.seconds(300); + + private static String formatForTest(String resourceName) { + return resourceName + "-" + NAME_SUFFIX; + } + + @Test + public void testPublisherSubscriber() throws Exception { + TopicName topicName = + TopicName.create(ServiceOptions.getDefaultProjectId(), formatForTest("test-topic")); + SubscriptionName subscriptionName = + SubscriptionName.create( + ServiceOptions.getDefaultProjectId(), formatForTest("test-subscription")); + try (TopicAdminClient publisherClient = TopicAdminClient.create(); + SubscriptionAdminClient subscriberClient = SubscriptionAdminClient.create()) { + publisherClient.createTopic(topicName); + subscriberClient.createSubscription( + subscriptionName, topicName, PushConfig.getDefaultInstance(), 0); + + testPublisherSubscriberHelper(topicName, subscriptionName); + + subscriberClient.deleteSubscription(subscriptionName); + publisherClient.deleteTopic(topicName); + } + } + + private void testPublisherSubscriberHelper(TopicName topicName, SubscriptionName subscriptionName) + throws Exception { + String messageToPublish = "my-message"; + + Publisher publisher = null; + try { + publisher = Publisher.defaultBuilder(topicName).build(); + PublisherSnippets snippets = new PublisherSnippets(publisher); + final SettableApiFuture done = SettableApiFuture.create(); + ApiFutures.addCallback( + snippets.publish(messageToPublish), + new ApiFutureCallback() { + public void onSuccess(String messageId) { + done.set(null); + } + + public void onFailure(Throwable t) { + done.setException(t); + } + }); + done.get(); + } finally { + if (publisher != null) { + publisher.shutdown(); + } + } + + final BlockingQueue queue = new ArrayBlockingQueue<>(1); + final SettableApiFuture done = SettableApiFuture.create(); + final SettableApiFuture received = SettableApiFuture.create(); + SubscriberSnippets snippets = + new SubscriberSnippets( + subscriptionName, + new MessageReceiverSnippets(queue).messageReceiver(), + done, + MoreExecutors.directExecutor()); + new Thread( + new Runnable() { + @Override + public void run() { + try { + received.set(queue.poll(10, TimeUnit.MINUTES)); + } catch (InterruptedException e) { + received.set(null); + } + done.set(null); // signal the subscriber to clean up + } + }) + .start(); + snippets.startAndWait(); // blocks until done is set + + PubsubMessage message = received.get(); + assertNotNull(message); + assertEquals(message.getData().toStringUtf8(), messageToPublish); + } +} diff --git a/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITSubscriberClientSnippets.java b/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITSubscriptionAdminClientSnippets.java similarity index 68% rename from google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITSubscriberClientSnippets.java rename to google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITSubscriptionAdminClientSnippets.java index 50fc5b52ac93..82caac5d5288 100644 --- a/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITSubscriberClientSnippets.java +++ b/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITSubscriptionAdminClientSnippets.java @@ -25,7 +25,7 @@ import com.google.cloud.Role; import com.google.cloud.pubsub.spi.v1.PagedResponseWrappers.ListSubscriptionsPagedResponse; import com.google.cloud.pubsub.spi.v1.Publisher; -import com.google.cloud.pubsub.spi.v1.PublisherClient; +import com.google.cloud.pubsub.spi.v1.TopicAdminClient; import com.google.common.collect.Iterables; import com.google.iam.v1.Policy; import com.google.iam.v1.TestIamPermissionsResponse; @@ -47,13 +47,13 @@ import org.junit.Test; import org.junit.rules.Timeout; -public class ITSubscriberClientSnippets { +public class ITSubscriptionAdminClientSnippets { private static final String NAME_SUFFIX = UUID.randomUUID().toString(); private static String projectId; - private static SubscriberClientSnippets subscriberClientSnippets; + private static SubscriptionAdminClientSnippets subscriptionAdminClientSnippets; private static String[] topics = { formatForTest("topic-1"), @@ -73,8 +73,8 @@ private static String formatForTest(String resourceName) { @BeforeClass public static void beforeClass() { - subscriberClientSnippets = new SubscriberClientSnippets(); - projectId = subscriberClientSnippets.getProjectId(); + subscriptionAdminClientSnippets = new SubscriptionAdminClientSnippets(); + projectId = subscriptionAdminClientSnippets.getProjectId(); } @Before @@ -82,36 +82,19 @@ public void setUp() throws Exception { Cleanup.deleteTestTopicsAndSubscriptions(projectId, topics, subscriptions); } - private Subscription createSubscription(String topicName, String subscriptionName) - throws Exception { + @Test + public void createSubscriptionWithPushIsSuccessful() throws Exception { + String topicName = topics[0]; + String subscriptionName = subscriptions[0]; createTopic(topicName); + String endpoint = "https://" + projectId + ".appspot.com/push"; Subscription subscription = - subscriberClientSnippets.createSubscription(topicName, subscriptionName); + subscriptionAdminClientSnippets.createSubscriptionWithPushEndpoint(topicName, subscriptionName, endpoint); assertNotNull(subscription); - Subscription retrievedSubscription = subscriberClientSnippets.getSubscription(subscriptionName); + Subscription retrievedSubscription = subscriptionAdminClientSnippets.getSubscription(subscriptionName); assertNotNull(retrievedSubscription); assertEquals(subscription.getName(), retrievedSubscription.getName()); - return subscription; - } - - @Test - public void publishAndPullMessagesIsSuccessful() throws Exception { - String topicName = topics[0]; - String subscriptionName = subscriptions[0]; - createSubscription(topicName, subscriptionName); - Set messages = publishMessages(topicName, 5); - //pulls max 100 messages - PullResponse response = subscriberClientSnippets.pull(subscriptionName); - assertNotNull(response); - //remove messages that match sent - for (ReceivedMessage receivedMessage : response.getReceivedMessagesList()) { - String message = receivedMessage.getMessage().getData().toStringUtf8(); - if (messages.contains(message)) { - messages.remove(message); - } - } - //all messages published were received - assertTrue(messages.isEmpty()); + assertEquals(subscription.getPushConfig().getPushEndpoint(), endpoint); } @Test @@ -120,8 +103,8 @@ public void replacePushConfigIsSuccessful() throws Exception { String subscriptionName = subscriptions[0]; createSubscription(topicName, subscriptionName); String endpoint = "https://" + projectId + ".appspot.com/push"; - subscriberClientSnippets.replacePushConfig(subscriptionName, endpoint); - Subscription subscription = subscriberClientSnippets.getSubscription(subscriptionName); + subscriptionAdminClientSnippets.replacePushConfig(subscriptionName, endpoint); + Subscription subscription = subscriptionAdminClientSnippets.getSubscription(subscriptionName); assertNotNull(subscription.getPushConfig()); assertEquals(subscription.getPushConfig().getPushEndpoint(), endpoint); } @@ -137,7 +120,7 @@ public void listSubscriptionsRetrievesAllAddedSubscriptions() throws Exception { addedSubscriptions.add(createSubscription(topicName2, subscriptionName2)); boolean[] subFound = {false, false}; - ListSubscriptionsPagedResponse response = subscriberClientSnippets.listSubscriptions(); + ListSubscriptionsPagedResponse response = subscriptionAdminClientSnippets.listSubscriptions(); assertNotNull(response); Iterable subscriptions = response.iterateAllElements(); for (int i = 0; i < 2; i++) { @@ -153,9 +136,9 @@ public void deleteSubscriptionThrowsExceptionWhenRetrieved() throws Exception { String topicName = topics[0]; String subscriptionName = subscriptions[0]; createSubscription(topicName, subscriptionName); - subscriberClientSnippets.deleteSubscription(subscriptionName); + subscriptionAdminClientSnippets.deleteSubscription(subscriptionName); //expected to throw exception on retrieval - subscriberClientSnippets.getSubscription(subscriptionName); + subscriptionAdminClientSnippets.getSubscription(subscriptionName); } @Test @@ -163,7 +146,7 @@ public void subscriptionHasValidIamPolicy() throws Exception { String topicName = topics[0]; String subscriptionName = subscriptions[0]; createSubscription(topicName, subscriptionName); - Policy policy = subscriberClientSnippets.getSubscriptionPolicy(subscriptionName); + Policy policy = subscriptionAdminClientSnippets.getSubscriptionPolicy(subscriptionName); assertNotNull(policy); } @@ -172,33 +155,32 @@ public void replaceSubscriptionPolicyAndTestPermissionsIsSuccessful() throws Exc String topicName = topics[0]; String subscriptionName = subscriptions[0]; createSubscription(topicName, subscriptionName); - Policy policy = subscriberClientSnippets.replaceSubscriptionPolicy(subscriptionName); + Policy policy = subscriptionAdminClientSnippets.replaceSubscriptionPolicy(subscriptionName); assertNotNull(policy.getBindingsCount()); assertTrue(policy.getBindings(0).getRole().equalsIgnoreCase(Role.viewer().toString())); assertTrue(policy.getBindings(0).getMembers(0) .equalsIgnoreCase(Identity.allAuthenticatedUsers().toString())); TestIamPermissionsResponse response = - subscriberClientSnippets.testSubscriptionPermissions(subscriptionName); + subscriptionAdminClientSnippets.testSubscriptionPermissions(subscriptionName); assertTrue(response.getPermissionsList().contains("pubsub.subscriptions.get")); } private void createTopic(String name) throws Exception { - try (PublisherClient publisherClient = PublisherClient.create()) { - publisherClient.createTopic(TopicName.create(projectId, name)); + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + topicAdminClient.createTopic(TopicName.create(projectId, name)); } } - private Set publishMessages(String topicName, int numMessages) throws Exception { - Set messages = new HashSet<>(); - Publisher publisher = Publisher.newBuilder(TopicName.create(projectId, topicName)).build(); - for (int i = 1; i<= numMessages; i++) { - String message = formatForTest("message-" + i); - PubsubMessage pubsubMessage = PubsubMessage.newBuilder().setData( - ByteString.copyFromUtf8(message)).build(); - publisher.publish(pubsubMessage); - messages.add(message); - } - return messages; + private Subscription createSubscription(String topicName, String subscriptionName) + throws Exception { + createTopic(topicName); + Subscription subscription = + subscriptionAdminClientSnippets.createSubscription(topicName, subscriptionName); + assertNotNull(subscription); + Subscription retrievedSubscription = subscriptionAdminClientSnippets.getSubscription(subscriptionName); + assertNotNull(retrievedSubscription); + assertEquals(subscription.getName(), retrievedSubscription.getName()); + return subscription; } @After diff --git a/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITPublisherClientSnippets.java b/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITTopicAdminClientSnippets.java similarity index 77% rename from google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITPublisherClientSnippets.java rename to google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITTopicAdminClientSnippets.java index d607a1568d45..c3cd9cffc86e 100644 --- a/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITPublisherClientSnippets.java +++ b/google-cloud-examples/src/test/java/com/google/cloud/examples/pubsub/snippets/ITTopicAdminClientSnippets.java @@ -25,7 +25,7 @@ import com.google.cloud.Role; import com.google.cloud.pubsub.spi.v1.PagedResponseWrappers.ListTopicSubscriptionsPagedResponse; import com.google.cloud.pubsub.spi.v1.PagedResponseWrappers.ListTopicsPagedResponse; -import com.google.cloud.pubsub.spi.v1.SubscriberClient; +import com.google.cloud.pubsub.spi.v1.SubscriptionAdminClient; import com.google.common.collect.Iterables; import com.google.iam.v1.Policy; import com.google.iam.v1.TestIamPermissionsResponse; @@ -44,13 +44,13 @@ import org.junit.Test; import org.junit.rules.Timeout; -public class ITPublisherClientSnippets { +public class ITTopicAdminClientSnippets { private static final String NAME_SUFFIX = UUID.randomUUID().toString(); private static String projectId; - private static PublisherClientSnippets publisherClientSnippets; + private static TopicAdminClientSnippets topicAdminClientSnippets; private static String[] topics = { formatForTest("topic-1"), @@ -70,8 +70,8 @@ private static String formatForTest(String resourceName) { @BeforeClass public static void beforeClass() { - publisherClientSnippets = new PublisherClientSnippets(); - projectId = publisherClientSnippets.getProjectId(); + topicAdminClientSnippets = new TopicAdminClientSnippets(); + projectId = topicAdminClientSnippets.getProjectId(); } @Before @@ -82,9 +82,9 @@ public void setUp() throws Exception { @Test public void topicAddedIsSameAsRetrieved() throws Exception { String topicName = topics[0]; - Topic topicAdded = publisherClientSnippets.createTopic(topicName); + Topic topicAdded = topicAdminClientSnippets.createTopic(topicName); assertNotNull(topicAdded); - Topic topicRetrieved = publisherClientSnippets.getTopic(topicName); + Topic topicRetrieved = topicAdminClientSnippets.getTopic(topicName); assertEquals(topicAdded, topicRetrieved); } @@ -92,12 +92,12 @@ public void topicAddedIsSameAsRetrieved() throws Exception { public void listTopicsRetreivesAddedTopics() throws Exception { List addedTopics = new ArrayList<>(); String topicName1 = topics[0]; - addedTopics.add(publisherClientSnippets.createTopic(topicName1)); + addedTopics.add(topicAdminClientSnippets.createTopic(topicName1)); String topicName2 = topics[1]; - addedTopics.add(publisherClientSnippets.createTopic(topicName2)); + addedTopics.add(topicAdminClientSnippets.createTopic(topicName2)); boolean[] topicFound = {false, false}; - ListTopicsPagedResponse response = publisherClientSnippets.listTopics(); + ListTopicsPagedResponse response = topicAdminClientSnippets.listTopics(); assertNotNull(response); Iterable topics = response.iterateAllElements(); @@ -114,7 +114,7 @@ public void listTopicsRetreivesAddedTopics() throws Exception { public void listTopicSubscriptionsRetrievesAddedSubscriptions() throws Exception { List addedSubscriptions = new ArrayList<>(); String topicName1 = topics[0]; - publisherClientSnippets.createTopic(topicName1); + topicAdminClientSnippets.createTopic(topicName1); String subscriptionName1 = subscriptions[0]; String subscriptionName2 = subscriptions[1]; addedSubscriptions.add(createSubscription(topicName1, subscriptionName1)); @@ -123,7 +123,7 @@ public void listTopicSubscriptionsRetrievesAddedSubscriptions() throws Exception boolean[] subFound = {false, false}; ListTopicSubscriptionsPagedResponse response = - publisherClientSnippets.listTopicSubscriptions(topicName1); + topicAdminClientSnippets.listTopicSubscriptions(topicName1); assertNotNull(response); @@ -139,37 +139,37 @@ public void listTopicSubscriptionsRetrievesAddedSubscriptions() throws Exception @Test(expected = ApiException.class) public void deletedTopicIsNotRetrievableAndThrowsException() throws Exception { String topicName = topics[0]; - Topic topicAdded = publisherClientSnippets.createTopic(topicName); + Topic topicAdded = topicAdminClientSnippets.createTopic(topicName); assertNotNull(topicAdded); - TopicName formattedName = publisherClientSnippets.deleteTopic(topicName); + TopicName formattedName = topicAdminClientSnippets.deleteTopic(topicName); assertNotNull(formattedName); - publisherClientSnippets.getTopic(topicName); + topicAdminClientSnippets.getTopic(topicName); } @Test public void topicPolicyIsCorrectlyRetrieved() throws Exception { String topicName = topics[0]; - publisherClientSnippets.createTopic(topicName); - Policy policy = publisherClientSnippets.getTopicPolicy(topicName); + topicAdminClientSnippets.createTopic(topicName); + Policy policy = topicAdminClientSnippets.getTopicPolicy(topicName); assertNotNull(policy); } @Test public void replaceTopicPolicyAndTestPermissionsIsSuccessful() throws Exception { String topicName = topics[0]; - publisherClientSnippets.createTopic(topicName); - Policy policy = publisherClientSnippets.replaceTopicPolicy(topicName); + topicAdminClientSnippets.createTopic(topicName); + Policy policy = topicAdminClientSnippets.replaceTopicPolicy(topicName); assertNotNull(policy.getBindingsCount()); assertTrue(policy.getBindings(0).getRole().equalsIgnoreCase(Role.viewer().toString())); assertTrue(policy.getBindings(0).getMembers(0) .equalsIgnoreCase(Identity.allAuthenticatedUsers().toString())); - TestIamPermissionsResponse response = publisherClientSnippets.testTopicPermissions(topicName); + TestIamPermissionsResponse response = topicAdminClientSnippets.testTopicPermissions(topicName); assertTrue(response.getPermissionsList().contains("pubsub.topics.get")); } private String createSubscription(String topic, String subscriptionName) throws Exception { - try (SubscriberClient subscriberClient = SubscriberClient.create()) { - Subscription subscription = subscriberClient.createSubscription( + try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { + Subscription subscription = subscriptionAdminClient.createSubscription( SubscriptionName.create(projectId, subscriptionName), TopicName.create(projectId, topic), PushConfig.getDefaultInstance(), 0); return subscription.getName(); diff --git a/google-cloud-language/pom.xml b/google-cloud-language/pom.xml index 5116fb1a435b..6c3e3f43fbc3 100644 --- a/google-cloud-language/pom.xml +++ b/google-cloud-language/pom.xml @@ -2,6 +2,7 @@ 4.0.0 google-cloud-language + ${beta.version} jar Google Cloud Natural Language https://github.com/GoogleCloudPlatform/google-cloud-java/tree/master/google-cloud-language @@ -11,10 +12,11 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-language + ${project.version} @@ -30,7 +32,18 @@ com.google.api.grpc grpc-google-cloud-language-v1 - 0.1.5 + 0.1.6 + + + io.grpc + grpc-all + + + + + com.google.api.grpc + grpc-google-cloud-language-v1beta2 + 0.1.6 io.grpc @@ -87,6 +100,22 @@ + + org.codehaus.mojo + properties-maven-plugin + 1.0-alpha-2 + + + generate-resources + + write-project-properties + + + ${project.build.outputDirectory}/project.properties + + + + org.codehaus.mojo build-helper-maven-plugin diff --git a/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1/LanguageServiceClient.java b/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1/LanguageServiceClient.java index d36a394e2fc1..e52b83183e25 100644 --- a/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1/LanguageServiceClient.java +++ b/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1/LanguageServiceClient.java @@ -238,8 +238,8 @@ private final AnalyzeSentimentResponse analyzeSentiment(AnalyzeSentimentRequest // AUTO-GENERATED DOCUMENTATION AND METHOD /** - * Finds named entities (currently finds proper names) in the text, entity types, salience, - * mentions for each entity, and other properties. + * Finds named entities (currently proper names and common nouns) in the text along with entity + * types, salience, mentions for each entity, and other properties. * *

    Sample code: * @@ -268,8 +268,8 @@ public final AnalyzeEntitiesResponse analyzeEntities( // AUTO-GENERATED DOCUMENTATION AND METHOD /** - * Finds named entities (currently finds proper names) in the text, entity types, salience, - * mentions for each entity, and other properties. + * Finds named entities (currently proper names and common nouns) in the text along with entity + * types, salience, mentions for each entity, and other properties. * *

    Sample code: * @@ -294,8 +294,8 @@ public final AnalyzeEntitiesResponse analyzeEntities(AnalyzeEntitiesRequest requ // AUTO-GENERATED DOCUMENTATION AND METHOD /** - * Finds named entities (currently finds proper names) in the text, entity types, salience, - * mentions for each entity, and other properties. + * Finds named entities (currently proper names and common nouns) in the text along with entity + * types, salience, mentions for each entity, and other properties. * *

    Sample code: * diff --git a/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1/LanguageServiceSettings.java b/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1/LanguageServiceSettings.java index a28ce690798d..2efab91f55de 100644 --- a/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1/LanguageServiceSettings.java +++ b/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1/LanguageServiceSettings.java @@ -16,6 +16,7 @@ package com.google.cloud.language.spi.v1; import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; import com.google.api.gax.core.RetrySettings; import com.google.api.gax.grpc.ChannelProvider; import com.google.api.gax.grpc.ClientSettings; @@ -73,12 +74,6 @@ @Generated("by GAPIC v0.0.5") @ExperimentalApi public class LanguageServiceSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "language.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder().add("https://www.googleapis.com/auth/cloud-platform").build(); @@ -86,6 +81,11 @@ public class LanguageServiceSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final SimpleCallSettings analyzeSentimentSettings; private final SimpleCallSettings @@ -121,14 +121,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "language.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -144,15 +139,19 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = LanguageServiceSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty( + LanguageServiceSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ diff --git a/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1beta2/LanguageServiceClient.java b/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1beta2/LanguageServiceClient.java new file mode 100644 index 000000000000..06ae5526a0f1 --- /dev/null +++ b/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1beta2/LanguageServiceClient.java @@ -0,0 +1,589 @@ +/* + * Copyright 2017, Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.language.spi.v1beta2; + +import com.google.api.gax.grpc.ChannelAndExecutor; +import com.google.api.gax.grpc.UnaryCallable; +import com.google.cloud.language.v1beta2.AnalyzeEntitiesRequest; +import com.google.cloud.language.v1beta2.AnalyzeEntitiesResponse; +import com.google.cloud.language.v1beta2.AnalyzeEntitySentimentRequest; +import com.google.cloud.language.v1beta2.AnalyzeEntitySentimentResponse; +import com.google.cloud.language.v1beta2.AnalyzeSentimentRequest; +import com.google.cloud.language.v1beta2.AnalyzeSentimentResponse; +import com.google.cloud.language.v1beta2.AnalyzeSyntaxRequest; +import com.google.cloud.language.v1beta2.AnalyzeSyntaxResponse; +import com.google.cloud.language.v1beta2.AnnotateTextRequest; +import com.google.cloud.language.v1beta2.AnnotateTextRequest.Features; +import com.google.cloud.language.v1beta2.AnnotateTextResponse; +import com.google.cloud.language.v1beta2.Document; +import com.google.cloud.language.v1beta2.EncodingType; +import com.google.protobuf.ExperimentalApi; +import io.grpc.ManagedChannel; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND SERVICE +/** + * Service Description: Provides text analysis operations such as sentiment analysis and entity + * recognition. + * + *

    This class provides the ability to make remote calls to the backing service through method + * calls that map to API methods. Sample code to get started: + * + *

    + * 
    + * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    + *   Document document = Document.newBuilder().build();
    + *   AnalyzeSentimentResponse response = languageServiceClient.analyzeSentiment(document);
    + * }
    + * 
    + * 
    + * + *

    Note: close() needs to be called on the languageServiceClient object to clean up resources + * such as threads. In the example above, try-with-resources is used, which automatically calls + * close(). + * + *

    The surface of this class includes several types of Java methods for each of the API's + * methods: + * + *

      + *
    1. A "flattened" method. With this type of method, the fields of the request type have been + * converted into function parameters. It may be the case that not all fields are available as + * parameters, and not every API method will have a flattened method entry point. + *
    2. A "request object" method. This type of method only takes one parameter, a request object, + * which must be constructed before the call. Not every API method will have a request object + * method. + *
    3. A "callable" method. This type of method takes no parameters and returns an immutable API + * callable object, which can be used to initiate calls to the service. + *
    + * + *

    See the individual methods for example code. + * + *

    Many parameters require resource names to be formatted in a particular way. To assist with + * these names, this class includes a format method for each type of name, and additionally a parse + * method to extract the individual identifiers contained within names that are returned. + * + *

    This class can be customized by passing in a custom instance of LanguageServiceSettings to + * create(). For example: + * + *

    + * 
    + * InstantiatingChannelProvider channelProvider =
    + *     LanguageServiceSettings.defaultChannelProviderBuilder()
    + *         .setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
    + *         .build();
    + * LanguageServiceSettings languageServiceSettings =
    + *     LanguageServiceSettings.defaultBuilder().setChannelProvider(channelProvider).build();
    + * LanguageServiceClient languageServiceClient =
    + *     LanguageServiceClient.create(languageServiceSettings);
    + * 
    + * 
    + */ +@Generated("by GAPIC") +@ExperimentalApi +public class LanguageServiceClient implements AutoCloseable { + private final LanguageServiceSettings settings; + private final ScheduledExecutorService executor; + private final ManagedChannel channel; + private final List closeables = new ArrayList<>(); + + private final UnaryCallable + analyzeSentimentCallable; + private final UnaryCallable + analyzeEntitiesCallable; + private final UnaryCallable + analyzeEntitySentimentCallable; + private final UnaryCallable analyzeSyntaxCallable; + private final UnaryCallable annotateTextCallable; + + /** Constructs an instance of LanguageServiceClient with default settings. */ + public static final LanguageServiceClient create() throws IOException { + return create(LanguageServiceSettings.defaultBuilder().build()); + } + + /** + * Constructs an instance of LanguageServiceClient, using the given settings. The channels are + * created based on the settings passed in, or defaults for any settings that are not set. + */ + public static final LanguageServiceClient create(LanguageServiceSettings settings) + throws IOException { + return new LanguageServiceClient(settings); + } + + /** + * Constructs an instance of LanguageServiceClient, using the given settings. This is protected so + * that it easy to make a subclass, but otherwise, the static factory methods should be preferred. + */ + protected LanguageServiceClient(LanguageServiceSettings settings) throws IOException { + this.settings = settings; + ChannelAndExecutor channelAndExecutor = settings.getChannelAndExecutor(); + this.executor = channelAndExecutor.getExecutor(); + this.channel = channelAndExecutor.getChannel(); + + this.analyzeSentimentCallable = + UnaryCallable.create(settings.analyzeSentimentSettings(), this.channel, this.executor); + this.analyzeEntitiesCallable = + UnaryCallable.create(settings.analyzeEntitiesSettings(), this.channel, this.executor); + this.analyzeEntitySentimentCallable = + UnaryCallable.create( + settings.analyzeEntitySentimentSettings(), this.channel, this.executor); + this.analyzeSyntaxCallable = + UnaryCallable.create(settings.analyzeSyntaxSettings(), this.channel, this.executor); + this.annotateTextCallable = + UnaryCallable.create(settings.annotateTextSettings(), this.channel, this.executor); + + if (settings.getChannelProvider().shouldAutoClose()) { + closeables.add( + new Closeable() { + @Override + public void close() throws IOException { + channel.shutdown(); + } + }); + } + if (settings.getExecutorProvider().shouldAutoClose()) { + closeables.add( + new Closeable() { + @Override + public void close() throws IOException { + executor.shutdown(); + } + }); + } + } + + public final LanguageServiceSettings getSettings() { + return settings; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Analyzes the sentiment of the provided text. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   AnalyzeSentimentResponse response = languageServiceClient.analyzeSentiment(document);
    +   * }
    +   * 
    + * + * @param document Input document. Currently, `analyzeSentiment` only supports English text + * ([Document.language][google.cloud.language.v1beta2.Document.language]="EN"). + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final AnalyzeSentimentResponse analyzeSentiment(Document document) { + + AnalyzeSentimentRequest request = + AnalyzeSentimentRequest.newBuilder().setDocument(document).build(); + return analyzeSentiment(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Analyzes the sentiment of the provided text. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   AnalyzeSentimentRequest request = AnalyzeSentimentRequest.newBuilder()
    +   *     .setDocument(document)
    +   *     .build();
    +   *   AnalyzeSentimentResponse response = languageServiceClient.analyzeSentiment(request);
    +   * }
    +   * 
    + * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + private final AnalyzeSentimentResponse analyzeSentiment(AnalyzeSentimentRequest request) { + return analyzeSentimentCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Analyzes the sentiment of the provided text. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   AnalyzeSentimentRequest request = AnalyzeSentimentRequest.newBuilder()
    +   *     .setDocument(document)
    +   *     .build();
    +   *   ApiFuture<AnalyzeSentimentResponse> future = languageServiceClient.analyzeSentimentCallable().futureCall(request);
    +   *   // Do something
    +   *   AnalyzeSentimentResponse response = future.get();
    +   * }
    +   * 
    + */ + public final UnaryCallable + analyzeSentimentCallable() { + return analyzeSentimentCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Finds named entities (currently proper names and common nouns) in the text along with entity + * types, salience, mentions for each entity, and other properties. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   EncodingType encodingType = EncodingType.NONE;
    +   *   AnalyzeEntitiesResponse response = languageServiceClient.analyzeEntities(document, encodingType);
    +   * }
    +   * 
    + * + * @param document Input document. + * @param encodingType The encoding type used by the API to calculate offsets. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final AnalyzeEntitiesResponse analyzeEntities( + Document document, EncodingType encodingType) { + + AnalyzeEntitiesRequest request = + AnalyzeEntitiesRequest.newBuilder() + .setDocument(document) + .setEncodingType(encodingType) + .build(); + return analyzeEntities(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Finds named entities (currently proper names and common nouns) in the text along with entity + * types, salience, mentions for each entity, and other properties. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   EncodingType encodingType = EncodingType.NONE;
    +   *   AnalyzeEntitiesRequest request = AnalyzeEntitiesRequest.newBuilder()
    +   *     .setDocument(document)
    +   *     .setEncodingType(encodingType)
    +   *     .build();
    +   *   AnalyzeEntitiesResponse response = languageServiceClient.analyzeEntities(request);
    +   * }
    +   * 
    + * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final AnalyzeEntitiesResponse analyzeEntities(AnalyzeEntitiesRequest request) { + return analyzeEntitiesCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Finds named entities (currently proper names and common nouns) in the text along with entity + * types, salience, mentions for each entity, and other properties. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   EncodingType encodingType = EncodingType.NONE;
    +   *   AnalyzeEntitiesRequest request = AnalyzeEntitiesRequest.newBuilder()
    +   *     .setDocument(document)
    +   *     .setEncodingType(encodingType)
    +   *     .build();
    +   *   ApiFuture<AnalyzeEntitiesResponse> future = languageServiceClient.analyzeEntitiesCallable().futureCall(request);
    +   *   // Do something
    +   *   AnalyzeEntitiesResponse response = future.get();
    +   * }
    +   * 
    + */ + public final UnaryCallable + analyzeEntitiesCallable() { + return analyzeEntitiesCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Finds entities, similar to + * [AnalyzeEntities][google.cloud.language.v1beta2.LanguageService.AnalyzeEntities] in the text + * and analyzes sentiment associated with each entity and its mentions. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   EncodingType encodingType = EncodingType.NONE;
    +   *   AnalyzeEntitySentimentResponse response = languageServiceClient.analyzeEntitySentiment(document, encodingType);
    +   * }
    +   * 
    + * + * @param document Input document. + * @param encodingType The encoding type used by the API to calculate offsets. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final AnalyzeEntitySentimentResponse analyzeEntitySentiment( + Document document, EncodingType encodingType) { + + AnalyzeEntitySentimentRequest request = + AnalyzeEntitySentimentRequest.newBuilder() + .setDocument(document) + .setEncodingType(encodingType) + .build(); + return analyzeEntitySentiment(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Finds entities, similar to + * [AnalyzeEntities][google.cloud.language.v1beta2.LanguageService.AnalyzeEntities] in the text + * and analyzes sentiment associated with each entity and its mentions. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   EncodingType encodingType = EncodingType.NONE;
    +   *   AnalyzeEntitySentimentRequest request = AnalyzeEntitySentimentRequest.newBuilder()
    +   *     .setDocument(document)
    +   *     .setEncodingType(encodingType)
    +   *     .build();
    +   *   AnalyzeEntitySentimentResponse response = languageServiceClient.analyzeEntitySentiment(request);
    +   * }
    +   * 
    + * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final AnalyzeEntitySentimentResponse analyzeEntitySentiment( + AnalyzeEntitySentimentRequest request) { + return analyzeEntitySentimentCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Finds entities, similar to + * [AnalyzeEntities][google.cloud.language.v1beta2.LanguageService.AnalyzeEntities] in the text + * and analyzes sentiment associated with each entity and its mentions. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   EncodingType encodingType = EncodingType.NONE;
    +   *   AnalyzeEntitySentimentRequest request = AnalyzeEntitySentimentRequest.newBuilder()
    +   *     .setDocument(document)
    +   *     .setEncodingType(encodingType)
    +   *     .build();
    +   *   ApiFuture<AnalyzeEntitySentimentResponse> future = languageServiceClient.analyzeEntitySentimentCallable().futureCall(request);
    +   *   // Do something
    +   *   AnalyzeEntitySentimentResponse response = future.get();
    +   * }
    +   * 
    + */ + public final UnaryCallable + analyzeEntitySentimentCallable() { + return analyzeEntitySentimentCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Analyzes the syntax of the text and provides sentence boundaries and tokenization along with + * part of speech tags, dependency trees, and other properties. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   EncodingType encodingType = EncodingType.NONE;
    +   *   AnalyzeSyntaxResponse response = languageServiceClient.analyzeSyntax(document, encodingType);
    +   * }
    +   * 
    + * + * @param document Input document. + * @param encodingType The encoding type used by the API to calculate offsets. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final AnalyzeSyntaxResponse analyzeSyntax(Document document, EncodingType encodingType) { + + AnalyzeSyntaxRequest request = + AnalyzeSyntaxRequest.newBuilder() + .setDocument(document) + .setEncodingType(encodingType) + .build(); + return analyzeSyntax(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Analyzes the syntax of the text and provides sentence boundaries and tokenization along with + * part of speech tags, dependency trees, and other properties. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   EncodingType encodingType = EncodingType.NONE;
    +   *   AnalyzeSyntaxRequest request = AnalyzeSyntaxRequest.newBuilder()
    +   *     .setDocument(document)
    +   *     .setEncodingType(encodingType)
    +   *     .build();
    +   *   AnalyzeSyntaxResponse response = languageServiceClient.analyzeSyntax(request);
    +   * }
    +   * 
    + * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final AnalyzeSyntaxResponse analyzeSyntax(AnalyzeSyntaxRequest request) { + return analyzeSyntaxCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Analyzes the syntax of the text and provides sentence boundaries and tokenization along with + * part of speech tags, dependency trees, and other properties. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   EncodingType encodingType = EncodingType.NONE;
    +   *   AnalyzeSyntaxRequest request = AnalyzeSyntaxRequest.newBuilder()
    +   *     .setDocument(document)
    +   *     .setEncodingType(encodingType)
    +   *     .build();
    +   *   ApiFuture<AnalyzeSyntaxResponse> future = languageServiceClient.analyzeSyntaxCallable().futureCall(request);
    +   *   // Do something
    +   *   AnalyzeSyntaxResponse response = future.get();
    +   * }
    +   * 
    + */ + public final UnaryCallable analyzeSyntaxCallable() { + return analyzeSyntaxCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * A convenience method that provides all syntax, sentiment, and entity features in one call. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   AnnotateTextRequest.Features features = AnnotateTextRequest.Features.newBuilder().build();
    +   *   EncodingType encodingType = EncodingType.NONE;
    +   *   AnnotateTextResponse response = languageServiceClient.annotateText(document, features, encodingType);
    +   * }
    +   * 
    + * + * @param document Input document. + * @param features The enabled features. + * @param encodingType The encoding type used by the API to calculate offsets. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final AnnotateTextResponse annotateText( + Document document, AnnotateTextRequest.Features features, EncodingType encodingType) { + + AnnotateTextRequest request = + AnnotateTextRequest.newBuilder() + .setDocument(document) + .setFeatures(features) + .setEncodingType(encodingType) + .build(); + return annotateText(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * A convenience method that provides all syntax, sentiment, and entity features in one call. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   AnnotateTextRequest.Features features = AnnotateTextRequest.Features.newBuilder().build();
    +   *   EncodingType encodingType = EncodingType.NONE;
    +   *   AnnotateTextRequest request = AnnotateTextRequest.newBuilder()
    +   *     .setDocument(document)
    +   *     .setFeatures(features)
    +   *     .setEncodingType(encodingType)
    +   *     .build();
    +   *   AnnotateTextResponse response = languageServiceClient.annotateText(request);
    +   * }
    +   * 
    + * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final AnnotateTextResponse annotateText(AnnotateTextRequest request) { + return annotateTextCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * A convenience method that provides all syntax, sentiment, and entity features in one call. + * + *

    Sample code: + * + *

    
    +   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    +   *   Document document = Document.newBuilder().build();
    +   *   AnnotateTextRequest.Features features = AnnotateTextRequest.Features.newBuilder().build();
    +   *   EncodingType encodingType = EncodingType.NONE;
    +   *   AnnotateTextRequest request = AnnotateTextRequest.newBuilder()
    +   *     .setDocument(document)
    +   *     .setFeatures(features)
    +   *     .setEncodingType(encodingType)
    +   *     .build();
    +   *   ApiFuture<AnnotateTextResponse> future = languageServiceClient.annotateTextCallable().futureCall(request);
    +   *   // Do something
    +   *   AnnotateTextResponse response = future.get();
    +   * }
    +   * 
    + */ + public final UnaryCallable annotateTextCallable() { + return annotateTextCallable; + } + + /** + * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately + * cancelled. + */ + @Override + public final void close() throws Exception { + for (AutoCloseable closeable : closeables) { + closeable.close(); + } + } +} diff --git a/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1beta2/LanguageServiceSettings.java b/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1beta2/LanguageServiceSettings.java new file mode 100644 index 000000000000..144b5bc80709 --- /dev/null +++ b/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1beta2/LanguageServiceSettings.java @@ -0,0 +1,376 @@ +/* + * Copyright 2017, Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.language.spi.v1beta2; + +import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; +import com.google.api.gax.core.RetrySettings; +import com.google.api.gax.grpc.ChannelProvider; +import com.google.api.gax.grpc.ClientSettings; +import com.google.api.gax.grpc.ExecutorProvider; +import com.google.api.gax.grpc.InstantiatingChannelProvider; +import com.google.api.gax.grpc.InstantiatingExecutorProvider; +import com.google.api.gax.grpc.SimpleCallSettings; +import com.google.api.gax.grpc.UnaryCallSettings; +import com.google.cloud.language.v1beta2.AnalyzeEntitiesRequest; +import com.google.cloud.language.v1beta2.AnalyzeEntitiesResponse; +import com.google.cloud.language.v1beta2.AnalyzeEntitySentimentRequest; +import com.google.cloud.language.v1beta2.AnalyzeEntitySentimentResponse; +import com.google.cloud.language.v1beta2.AnalyzeSentimentRequest; +import com.google.cloud.language.v1beta2.AnalyzeSentimentResponse; +import com.google.cloud.language.v1beta2.AnalyzeSyntaxRequest; +import com.google.cloud.language.v1beta2.AnalyzeSyntaxResponse; +import com.google.cloud.language.v1beta2.AnnotateTextRequest; +import com.google.cloud.language.v1beta2.AnnotateTextResponse; +import com.google.cloud.language.v1beta2.LanguageServiceGrpc; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.google.protobuf.ExperimentalApi; +import io.grpc.Status; +import java.io.IOException; +import javax.annotation.Generated; +import org.joda.time.Duration; + +// AUTO-GENERATED DOCUMENTATION AND CLASS +/** + * Settings class to configure an instance of {@link LanguageServiceClient}. + * + *

    The default instance has everything set to sensible defaults: + * + *

      + *
    • The default service address (language.googleapis.com) and default port (443) are used. + *
    • Credentials are acquired automatically through Application Default Credentials. + *
    • Retries are configured for idempotent methods but not for non-idempotent methods. + *
    + * + *

    The builder of this class is recursive, so contained classes are themselves builders. When + * build() is called, the tree of builders is called to create the complete settings object. For + * example, to set the total timeout of analyzeSentiment to 30 seconds: + * + *

    + * 
    + * LanguageServiceSettings.Builder languageServiceSettingsBuilder =
    + *     LanguageServiceSettings.defaultBuilder();
    + * languageServiceSettingsBuilder.analyzeSentimentSettings().getRetrySettingsBuilder()
    + *     .setTotalTimeout(Duration.standardSeconds(30));
    + * LanguageServiceSettings languageServiceSettings = languageServiceSettingsBuilder.build();
    + * 
    + * 
    + */ +@Generated("by GAPIC v0.0.5") +@ExperimentalApi +public class LanguageServiceSettings extends ClientSettings { + /** The default scopes of the service. */ + private static final ImmutableList DEFAULT_SERVICE_SCOPES = + ImmutableList.builder().add("https://www.googleapis.com/auth/cloud-platform").build(); + + private static final String DEFAULT_GAPIC_NAME = "gapic"; + private static final String DEFAULT_GAPIC_VERSION = ""; + + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + + private final SimpleCallSettings + analyzeSentimentSettings; + private final SimpleCallSettings + analyzeEntitiesSettings; + private final SimpleCallSettings + analyzeEntitySentimentSettings; + private final SimpleCallSettings + analyzeSyntaxSettings; + private final SimpleCallSettings annotateTextSettings; + + /** Returns the object with the settings used for calls to analyzeSentiment. */ + public SimpleCallSettings + analyzeSentimentSettings() { + return analyzeSentimentSettings; + } + + /** Returns the object with the settings used for calls to analyzeEntities. */ + public SimpleCallSettings + analyzeEntitiesSettings() { + return analyzeEntitiesSettings; + } + + /** Returns the object with the settings used for calls to analyzeEntitySentiment. */ + public SimpleCallSettings + analyzeEntitySentimentSettings() { + return analyzeEntitySentimentSettings; + } + + /** Returns the object with the settings used for calls to analyzeSyntax. */ + public SimpleCallSettings analyzeSyntaxSettings() { + return analyzeSyntaxSettings; + } + + /** Returns the object with the settings used for calls to annotateText. */ + public SimpleCallSettings annotateTextSettings() { + return annotateTextSettings; + } + + /** Returns a builder for the default ExecutorProvider for this service. */ + public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() { + return InstantiatingExecutorProvider.newBuilder(); + } + + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "language.googleapis.com:443"; + } + + /** Returns the default service scopes. */ + public static ImmutableList getDefaultServiceScopes() { + return DEFAULT_SERVICE_SCOPES; + } + + /** Returns a builder for the default credentials for this service. */ + public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilder() { + return GoogleCredentialsProvider.newBuilder().setScopesToApply(DEFAULT_SERVICE_SCOPES); + } + + /** Returns a builder for the default ChannelProvider for this service. */ + public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { + return InstantiatingChannelProvider.newBuilder() + .setEndpoint(getDefaultEndpoint()) + .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) + .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); + } + + private static String getGapicVersion() { + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty( + LanguageServiceSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; + } + + /** Returns a builder for this class with recommended defaults. */ + public static Builder defaultBuilder() { + return Builder.createDefault(); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder() { + return new Builder(); + } + + /** Returns a builder containing all the values of this settings class. */ + public Builder toBuilder() { + return new Builder(this); + } + + private LanguageServiceSettings(Builder settingsBuilder) throws IOException { + super(settingsBuilder.getExecutorProvider(), settingsBuilder.getChannelProvider()); + + analyzeSentimentSettings = settingsBuilder.analyzeSentimentSettings().build(); + analyzeEntitiesSettings = settingsBuilder.analyzeEntitiesSettings().build(); + analyzeEntitySentimentSettings = settingsBuilder.analyzeEntitySentimentSettings().build(); + analyzeSyntaxSettings = settingsBuilder.analyzeSyntaxSettings().build(); + annotateTextSettings = settingsBuilder.annotateTextSettings().build(); + } + + /** Builder for LanguageServiceSettings. */ + public static class Builder extends ClientSettings.Builder { + private final ImmutableList unaryMethodSettingsBuilders; + + private final SimpleCallSettings.Builder + analyzeSentimentSettings; + private final SimpleCallSettings.Builder + analyzeEntitiesSettings; + private final SimpleCallSettings.Builder< + AnalyzeEntitySentimentRequest, AnalyzeEntitySentimentResponse> + analyzeEntitySentimentSettings; + private final SimpleCallSettings.Builder + analyzeSyntaxSettings; + private final SimpleCallSettings.Builder + annotateTextSettings; + + private static final ImmutableMap> RETRYABLE_CODE_DEFINITIONS; + + static { + ImmutableMap.Builder> definitions = ImmutableMap.builder(); + definitions.put( + "idempotent", + Sets.immutableEnumSet( + Lists.newArrayList( + Status.Code.DEADLINE_EXCEEDED, Status.Code.UNAVAILABLE))); + definitions.put( + "non_idempotent", + Sets.immutableEnumSet(Lists.newArrayList(Status.Code.UNAVAILABLE))); + RETRYABLE_CODE_DEFINITIONS = definitions.build(); + } + + private static final ImmutableMap RETRY_PARAM_DEFINITIONS; + + static { + ImmutableMap.Builder definitions = ImmutableMap.builder(); + RetrySettings.Builder settingsBuilder = null; + settingsBuilder = + RetrySettings.newBuilder() + .setInitialRetryDelay(Duration.millis(100L)) + .setRetryDelayMultiplier(1.3) + .setMaxRetryDelay(Duration.millis(60000L)) + .setInitialRpcTimeout(Duration.millis(60000L)) + .setRpcTimeoutMultiplier(1.0) + .setMaxRpcTimeout(Duration.millis(60000L)) + .setTotalTimeout(Duration.millis(600000L)); + definitions.put("default", settingsBuilder); + RETRY_PARAM_DEFINITIONS = definitions.build(); + } + + private Builder() { + super(defaultChannelProviderBuilder().build()); + + analyzeSentimentSettings = + SimpleCallSettings.newBuilder(LanguageServiceGrpc.METHOD_ANALYZE_SENTIMENT); + + analyzeEntitiesSettings = + SimpleCallSettings.newBuilder(LanguageServiceGrpc.METHOD_ANALYZE_ENTITIES); + + analyzeEntitySentimentSettings = + SimpleCallSettings.newBuilder(LanguageServiceGrpc.METHOD_ANALYZE_ENTITY_SENTIMENT); + + analyzeSyntaxSettings = + SimpleCallSettings.newBuilder(LanguageServiceGrpc.METHOD_ANALYZE_SYNTAX); + + annotateTextSettings = + SimpleCallSettings.newBuilder(LanguageServiceGrpc.METHOD_ANNOTATE_TEXT); + + unaryMethodSettingsBuilders = + ImmutableList.of( + analyzeSentimentSettings, + analyzeEntitiesSettings, + analyzeEntitySentimentSettings, + analyzeSyntaxSettings, + annotateTextSettings); + } + + private static Builder createDefault() { + Builder builder = new Builder(); + + builder + .analyzeSentimentSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder + .analyzeEntitiesSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder + .analyzeEntitySentimentSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder + .analyzeSyntaxSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder + .annotateTextSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + return builder; + } + + private Builder(LanguageServiceSettings settings) { + super(settings); + + analyzeSentimentSettings = settings.analyzeSentimentSettings.toBuilder(); + analyzeEntitiesSettings = settings.analyzeEntitiesSettings.toBuilder(); + analyzeEntitySentimentSettings = settings.analyzeEntitySentimentSettings.toBuilder(); + analyzeSyntaxSettings = settings.analyzeSyntaxSettings.toBuilder(); + annotateTextSettings = settings.annotateTextSettings.toBuilder(); + + unaryMethodSettingsBuilders = + ImmutableList.of( + analyzeSentimentSettings, + analyzeEntitiesSettings, + analyzeEntitySentimentSettings, + analyzeSyntaxSettings, + annotateTextSettings); + } + + @Override + public Builder setExecutorProvider(ExecutorProvider executorProvider) { + super.setExecutorProvider(executorProvider); + return this; + } + + @Override + public Builder setChannelProvider(ChannelProvider channelProvider) { + super.setChannelProvider(channelProvider); + return this; + } + + /** + * Applies the given settings to all of the unary API methods in this service. Only values that + * are non-null will be applied, so this method is not capable of un-setting any values. + * + *

    Note: This method does not support applying settings to streaming methods. + */ + public Builder applyToAllUnaryMethods(UnaryCallSettings.Builder unaryCallSettings) + throws Exception { + super.applyToAllUnaryMethods(unaryMethodSettingsBuilders, unaryCallSettings); + return this; + } + + /** Returns the builder for the settings used for calls to analyzeSentiment. */ + public SimpleCallSettings.Builder + analyzeSentimentSettings() { + return analyzeSentimentSettings; + } + + /** Returns the builder for the settings used for calls to analyzeEntities. */ + public SimpleCallSettings.Builder + analyzeEntitiesSettings() { + return analyzeEntitiesSettings; + } + + /** Returns the builder for the settings used for calls to analyzeEntitySentiment. */ + public SimpleCallSettings.Builder + analyzeEntitySentimentSettings() { + return analyzeEntitySentimentSettings; + } + + /** Returns the builder for the settings used for calls to analyzeSyntax. */ + public SimpleCallSettings.Builder + analyzeSyntaxSettings() { + return analyzeSyntaxSettings; + } + + /** Returns the builder for the settings used for calls to annotateText. */ + public SimpleCallSettings.Builder + annotateTextSettings() { + return annotateTextSettings; + } + + @Override + public LanguageServiceSettings build() throws IOException { + return new LanguageServiceSettings(this); + } + } +} diff --git a/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1beta2/package-info.java b/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1beta2/package-info.java new file mode 100644 index 000000000000..39e9f44eb781 --- /dev/null +++ b/google-cloud-language/src/main/java/com/google/cloud/language/spi/v1beta2/package-info.java @@ -0,0 +1,38 @@ +/* + * Copyright 2017, Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * A client to Google Cloud Natural Language API. + * + *

    The interfaces provided are listed below, along with usage samples. + * + *

    ===================== LanguageServiceClient ===================== + * + *

    Service Description: Provides text analysis operations such as sentiment analysis and entity + * recognition. + * + *

    Sample for LanguageServiceClient: + * + *

    + * 
    + * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
    + *   Document document = Document.newBuilder().build();
    + *   AnalyzeSentimentResponse response = languageServiceClient.analyzeSentiment(document);
    + * }
    + * 
    + * 
    + */ +package com.google.cloud.language.spi.v1beta2; diff --git a/google-cloud-language/src/test/java/com/google/cloud/language/spi/v1/LanguageServiceClientTest.java b/google-cloud-language/src/test/java/com/google/cloud/language/spi/v1/LanguageServiceClientTest.java index 8fadd45dc42f..3d7fe8efa52d 100644 --- a/google-cloud-language/src/test/java/com/google/cloud/language/spi/v1/LanguageServiceClientTest.java +++ b/google-cloud-language/src/test/java/com/google/cloud/language/spi/v1/LanguageServiceClientTest.java @@ -99,7 +99,7 @@ public void analyzeSentimentTest() { @Test @SuppressWarnings("all") public void analyzeSentimentExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockLanguageService.addException(exception); try { @@ -108,7 +108,7 @@ public void analyzeSentimentExceptionTest() throws Exception { client.analyzeSentiment(document); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -137,7 +137,7 @@ public void analyzeEntitiesTest() { @Test @SuppressWarnings("all") public void analyzeEntitiesExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockLanguageService.addException(exception); try { @@ -147,7 +147,7 @@ public void analyzeEntitiesExceptionTest() throws Exception { client.analyzeEntities(document, encodingType); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -176,7 +176,7 @@ public void analyzeSyntaxTest() { @Test @SuppressWarnings("all") public void analyzeSyntaxExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockLanguageService.addException(exception); try { @@ -186,7 +186,7 @@ public void analyzeSyntaxExceptionTest() throws Exception { client.analyzeSyntax(document, encodingType); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -217,7 +217,7 @@ public void annotateTextTest() { @Test @SuppressWarnings("all") public void annotateTextExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockLanguageService.addException(exception); try { @@ -228,7 +228,7 @@ public void annotateTextExceptionTest() throws Exception { client.annotateText(document, features, encodingType); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } } diff --git a/google-cloud-language/src/test/java/com/google/cloud/language/spi/v1beta2/LanguageServiceClientTest.java b/google-cloud-language/src/test/java/com/google/cloud/language/spi/v1beta2/LanguageServiceClientTest.java new file mode 100644 index 000000000000..b0c4c5969c4b --- /dev/null +++ b/google-cloud-language/src/test/java/com/google/cloud/language/spi/v1beta2/LanguageServiceClientTest.java @@ -0,0 +1,277 @@ +/* + * Copyright 2017, Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.language.spi.v1beta2; + +import com.google.api.gax.grpc.ApiException; +import com.google.api.gax.testing.MockGrpcService; +import com.google.api.gax.testing.MockServiceHelper; +import com.google.cloud.language.v1beta2.AnalyzeEntitiesRequest; +import com.google.cloud.language.v1beta2.AnalyzeEntitiesResponse; +import com.google.cloud.language.v1beta2.AnalyzeEntitySentimentRequest; +import com.google.cloud.language.v1beta2.AnalyzeEntitySentimentResponse; +import com.google.cloud.language.v1beta2.AnalyzeSentimentRequest; +import com.google.cloud.language.v1beta2.AnalyzeSentimentResponse; +import com.google.cloud.language.v1beta2.AnalyzeSyntaxRequest; +import com.google.cloud.language.v1beta2.AnalyzeSyntaxResponse; +import com.google.cloud.language.v1beta2.AnnotateTextRequest; +import com.google.cloud.language.v1beta2.AnnotateTextRequest.Features; +import com.google.cloud.language.v1beta2.AnnotateTextResponse; +import com.google.cloud.language.v1beta2.Document; +import com.google.cloud.language.v1beta2.EncodingType; +import com.google.protobuf.GeneratedMessageV3; +import io.grpc.Status; +import io.grpc.StatusRuntimeException; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +@javax.annotation.Generated("by GAPIC") +public class LanguageServiceClientTest { + private static MockLanguageService mockLanguageService; + private static MockServiceHelper serviceHelper; + private LanguageServiceClient client; + + @BeforeClass + public static void startStaticServer() { + mockLanguageService = new MockLanguageService(); + serviceHelper = + new MockServiceHelper("in-process-1", Arrays.asList(mockLanguageService)); + serviceHelper.start(); + } + + @AfterClass + public static void stopServer() { + serviceHelper.stop(); + } + + @Before + public void setUp() throws IOException { + serviceHelper.reset(); + LanguageServiceSettings settings = + LanguageServiceSettings.defaultBuilder() + .setChannelProvider(serviceHelper.createChannelProvider()) + .build(); + client = LanguageServiceClient.create(settings); + } + + @After + public void tearDown() throws Exception { + client.close(); + } + + @Test + @SuppressWarnings("all") + public void analyzeSentimentTest() { + String language = "language-1613589672"; + AnalyzeSentimentResponse expectedResponse = + AnalyzeSentimentResponse.newBuilder().setLanguage(language).build(); + mockLanguageService.addResponse(expectedResponse); + + Document document = Document.newBuilder().build(); + + AnalyzeSentimentResponse actualResponse = client.analyzeSentiment(document); + Assert.assertEquals(expectedResponse, actualResponse); + + List actualRequests = mockLanguageService.getRequests(); + Assert.assertEquals(1, actualRequests.size()); + AnalyzeSentimentRequest actualRequest = (AnalyzeSentimentRequest) actualRequests.get(0); + + Assert.assertEquals(document, actualRequest.getDocument()); + } + + @Test + @SuppressWarnings("all") + public void analyzeSentimentExceptionTest() throws Exception { + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); + mockLanguageService.addException(exception); + + try { + Document document = Document.newBuilder().build(); + + client.analyzeSentiment(document); + Assert.fail("No exception raised"); + } catch (ApiException e) { + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); + } + } + + @Test + @SuppressWarnings("all") + public void analyzeEntitiesTest() { + String language = "language-1613589672"; + AnalyzeEntitiesResponse expectedResponse = + AnalyzeEntitiesResponse.newBuilder().setLanguage(language).build(); + mockLanguageService.addResponse(expectedResponse); + + Document document = Document.newBuilder().build(); + EncodingType encodingType = EncodingType.NONE; + + AnalyzeEntitiesResponse actualResponse = client.analyzeEntities(document, encodingType); + Assert.assertEquals(expectedResponse, actualResponse); + + List actualRequests = mockLanguageService.getRequests(); + Assert.assertEquals(1, actualRequests.size()); + AnalyzeEntitiesRequest actualRequest = (AnalyzeEntitiesRequest) actualRequests.get(0); + + Assert.assertEquals(document, actualRequest.getDocument()); + Assert.assertEquals(encodingType, actualRequest.getEncodingType()); + } + + @Test + @SuppressWarnings("all") + public void analyzeEntitiesExceptionTest() throws Exception { + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); + mockLanguageService.addException(exception); + + try { + Document document = Document.newBuilder().build(); + EncodingType encodingType = EncodingType.NONE; + + client.analyzeEntities(document, encodingType); + Assert.fail("No exception raised"); + } catch (ApiException e) { + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); + } + } + + @Test + @SuppressWarnings("all") + public void analyzeEntitySentimentTest() { + String language = "language-1613589672"; + AnalyzeEntitySentimentResponse expectedResponse = + AnalyzeEntitySentimentResponse.newBuilder().setLanguage(language).build(); + mockLanguageService.addResponse(expectedResponse); + + Document document = Document.newBuilder().build(); + EncodingType encodingType = EncodingType.NONE; + + AnalyzeEntitySentimentResponse actualResponse = + client.analyzeEntitySentiment(document, encodingType); + Assert.assertEquals(expectedResponse, actualResponse); + + List actualRequests = mockLanguageService.getRequests(); + Assert.assertEquals(1, actualRequests.size()); + AnalyzeEntitySentimentRequest actualRequest = + (AnalyzeEntitySentimentRequest) actualRequests.get(0); + + Assert.assertEquals(document, actualRequest.getDocument()); + Assert.assertEquals(encodingType, actualRequest.getEncodingType()); + } + + @Test + @SuppressWarnings("all") + public void analyzeEntitySentimentExceptionTest() throws Exception { + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); + mockLanguageService.addException(exception); + + try { + Document document = Document.newBuilder().build(); + EncodingType encodingType = EncodingType.NONE; + + client.analyzeEntitySentiment(document, encodingType); + Assert.fail("No exception raised"); + } catch (ApiException e) { + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); + } + } + + @Test + @SuppressWarnings("all") + public void analyzeSyntaxTest() { + String language = "language-1613589672"; + AnalyzeSyntaxResponse expectedResponse = + AnalyzeSyntaxResponse.newBuilder().setLanguage(language).build(); + mockLanguageService.addResponse(expectedResponse); + + Document document = Document.newBuilder().build(); + EncodingType encodingType = EncodingType.NONE; + + AnalyzeSyntaxResponse actualResponse = client.analyzeSyntax(document, encodingType); + Assert.assertEquals(expectedResponse, actualResponse); + + List actualRequests = mockLanguageService.getRequests(); + Assert.assertEquals(1, actualRequests.size()); + AnalyzeSyntaxRequest actualRequest = (AnalyzeSyntaxRequest) actualRequests.get(0); + + Assert.assertEquals(document, actualRequest.getDocument()); + Assert.assertEquals(encodingType, actualRequest.getEncodingType()); + } + + @Test + @SuppressWarnings("all") + public void analyzeSyntaxExceptionTest() throws Exception { + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); + mockLanguageService.addException(exception); + + try { + Document document = Document.newBuilder().build(); + EncodingType encodingType = EncodingType.NONE; + + client.analyzeSyntax(document, encodingType); + Assert.fail("No exception raised"); + } catch (ApiException e) { + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); + } + } + + @Test + @SuppressWarnings("all") + public void annotateTextTest() { + String language = "language-1613589672"; + AnnotateTextResponse expectedResponse = + AnnotateTextResponse.newBuilder().setLanguage(language).build(); + mockLanguageService.addResponse(expectedResponse); + + Document document = Document.newBuilder().build(); + AnnotateTextRequest.Features features = AnnotateTextRequest.Features.newBuilder().build(); + EncodingType encodingType = EncodingType.NONE; + + AnnotateTextResponse actualResponse = client.annotateText(document, features, encodingType); + Assert.assertEquals(expectedResponse, actualResponse); + + List actualRequests = mockLanguageService.getRequests(); + Assert.assertEquals(1, actualRequests.size()); + AnnotateTextRequest actualRequest = (AnnotateTextRequest) actualRequests.get(0); + + Assert.assertEquals(document, actualRequest.getDocument()); + Assert.assertEquals(features, actualRequest.getFeatures()); + Assert.assertEquals(encodingType, actualRequest.getEncodingType()); + } + + @Test + @SuppressWarnings("all") + public void annotateTextExceptionTest() throws Exception { + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); + mockLanguageService.addException(exception); + + try { + Document document = Document.newBuilder().build(); + AnnotateTextRequest.Features features = AnnotateTextRequest.Features.newBuilder().build(); + EncodingType encodingType = EncodingType.NONE; + + client.annotateText(document, features, encodingType); + Assert.fail("No exception raised"); + } catch (ApiException e) { + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); + } + } +} diff --git a/google-cloud-language/src/test/java/com/google/cloud/language/spi/v1beta2/MockLanguageService.java b/google-cloud-language/src/test/java/com/google/cloud/language/spi/v1beta2/MockLanguageService.java new file mode 100644 index 000000000000..21146ba5d120 --- /dev/null +++ b/google-cloud-language/src/test/java/com/google/cloud/language/spi/v1beta2/MockLanguageService.java @@ -0,0 +1,59 @@ +/* + * Copyright 2017, Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.language.spi.v1beta2; + +import com.google.api.gax.testing.MockGrpcService; +import com.google.protobuf.GeneratedMessageV3; +import io.grpc.ServerServiceDefinition; +import java.util.List; + +@javax.annotation.Generated("by GAPIC") +public class MockLanguageService implements MockGrpcService { + private final MockLanguageServiceImpl serviceImpl; + + public MockLanguageService() { + serviceImpl = new MockLanguageServiceImpl(); + } + + @Override + public List getRequests() { + return serviceImpl.getRequests(); + } + + @Override + public void addResponse(GeneratedMessageV3 response) { + serviceImpl.addResponse(response); + } + + @Override + public void addException(Exception exception) { + serviceImpl.addException(exception); + } + + public void setResponses(List responses) { + serviceImpl.setResponses(responses); + } + + @Override + public ServerServiceDefinition getServiceDefinition() { + return serviceImpl.bindService(); + } + + @Override + public void reset() { + serviceImpl.reset(); + } +} diff --git a/google-cloud-language/src/test/java/com/google/cloud/language/spi/v1beta2/MockLanguageServiceImpl.java b/google-cloud-language/src/test/java/com/google/cloud/language/spi/v1beta2/MockLanguageServiceImpl.java new file mode 100644 index 000000000000..766c4bb5f53b --- /dev/null +++ b/google-cloud-language/src/test/java/com/google/cloud/language/spi/v1beta2/MockLanguageServiceImpl.java @@ -0,0 +1,142 @@ +/* + * Copyright 2017, Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.language.spi.v1beta2; + +import com.google.cloud.language.v1beta2.AnalyzeEntitiesRequest; +import com.google.cloud.language.v1beta2.AnalyzeEntitiesResponse; +import com.google.cloud.language.v1beta2.AnalyzeEntitySentimentRequest; +import com.google.cloud.language.v1beta2.AnalyzeEntitySentimentResponse; +import com.google.cloud.language.v1beta2.AnalyzeSentimentRequest; +import com.google.cloud.language.v1beta2.AnalyzeSentimentResponse; +import com.google.cloud.language.v1beta2.AnalyzeSyntaxRequest; +import com.google.cloud.language.v1beta2.AnalyzeSyntaxResponse; +import com.google.cloud.language.v1beta2.AnnotateTextRequest; +import com.google.cloud.language.v1beta2.AnnotateTextResponse; +import com.google.cloud.language.v1beta2.LanguageServiceGrpc.LanguageServiceImplBase; +import com.google.protobuf.GeneratedMessageV3; +import io.grpc.stub.StreamObserver; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +@javax.annotation.Generated("by GAPIC") +public class MockLanguageServiceImpl extends LanguageServiceImplBase { + private ArrayList requests; + private Queue responses; + + public MockLanguageServiceImpl() { + requests = new ArrayList<>(); + responses = new LinkedList<>(); + } + + public List getRequests() { + return requests; + } + + public void addResponse(GeneratedMessageV3 response) { + responses.add(response); + } + + public void setResponses(List responses) { + this.responses = new LinkedList(responses); + } + + public void addException(Exception exception) { + responses.add(exception); + } + + public void reset() { + requests = new ArrayList<>(); + responses = new LinkedList<>(); + } + + @Override + public void analyzeSentiment( + AnalyzeSentimentRequest request, StreamObserver responseObserver) { + Object response = responses.remove(); + if (response instanceof AnalyzeSentimentResponse) { + requests.add(request); + responseObserver.onNext((AnalyzeSentimentResponse) response); + responseObserver.onCompleted(); + } else if (response instanceof Exception) { + responseObserver.onError((Exception) response); + } else { + responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); + } + } + + @Override + public void analyzeEntities( + AnalyzeEntitiesRequest request, StreamObserver responseObserver) { + Object response = responses.remove(); + if (response instanceof AnalyzeEntitiesResponse) { + requests.add(request); + responseObserver.onNext((AnalyzeEntitiesResponse) response); + responseObserver.onCompleted(); + } else if (response instanceof Exception) { + responseObserver.onError((Exception) response); + } else { + responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); + } + } + + @Override + public void analyzeEntitySentiment( + AnalyzeEntitySentimentRequest request, + StreamObserver responseObserver) { + Object response = responses.remove(); + if (response instanceof AnalyzeEntitySentimentResponse) { + requests.add(request); + responseObserver.onNext((AnalyzeEntitySentimentResponse) response); + responseObserver.onCompleted(); + } else if (response instanceof Exception) { + responseObserver.onError((Exception) response); + } else { + responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); + } + } + + @Override + public void analyzeSyntax( + AnalyzeSyntaxRequest request, StreamObserver responseObserver) { + Object response = responses.remove(); + if (response instanceof AnalyzeSyntaxResponse) { + requests.add(request); + responseObserver.onNext((AnalyzeSyntaxResponse) response); + responseObserver.onCompleted(); + } else if (response instanceof Exception) { + responseObserver.onError((Exception) response); + } else { + responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); + } + } + + @Override + public void annotateText( + AnnotateTextRequest request, StreamObserver responseObserver) { + Object response = responses.remove(); + if (response instanceof AnnotateTextResponse) { + requests.add(request); + responseObserver.onNext((AnnotateTextResponse) response); + responseObserver.onCompleted(); + } else if (response instanceof Exception) { + responseObserver.onError((Exception) response); + } else { + responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); + } + } +} diff --git a/google-cloud-logging/README.md b/google-cloud-logging/README.md index 9846fed5994b..c4f8a42dd84b 100644 --- a/google-cloud-logging/README.md +++ b/google-cloud-logging/README.md @@ -26,16 +26,16 @@ Add this to your pom.xml file com.google.cloud google-cloud-logging - 0.10.0-beta + 0.12.0-beta ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-logging:0.10.0-beta' +compile 'com.google.cloud:google-cloud-logging:0.12.0-beta' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-logging" % "0.10.0-beta" +libraryDependencies += "com.google.cloud" % "google-cloud-logging" % "0.12.0-beta" ``` Example Application diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index e81b0222cdb3..6e1a85e84e1f 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -12,10 +12,11 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-logging + ${project.version} @@ -88,6 +89,22 @@ + + org.codehaus.mojo + properties-maven-plugin + 1.0-alpha-2 + + + generate-resources + + write-project-properties + + + ${project.build.outputDirectory}/project.properties + + + + org.codehaus.mojo build-helper-maven-plugin diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingHandler.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingHandler.java index d82b68db74f3..1474640b5bba 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingHandler.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingHandler.java @@ -18,16 +18,19 @@ import static com.google.common.base.MoreObjects.firstNonNull; +import com.google.api.gax.core.ApiFuture; +import com.google.api.gax.core.ApiFutureCallback; +import com.google.api.gax.core.ApiFutures; import com.google.cloud.MonitoredResource; import com.google.cloud.logging.Logging.WriteOption; -import com.google.api.gax.core.ApiFutures; -import com.google.api.gax.core.ApiFutureCallback; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.Uninterruptibles; import java.util.ArrayList; import java.util.Collections; -import java.util.LinkedList; +import java.util.IdentityHashMap; import java.util.List; +import java.util.Set; import java.util.logging.ErrorManager; import java.util.logging.Filter; import java.util.logging.Formatter; @@ -120,6 +123,10 @@ public class LoggingHandler extends Handler { // https://github.com/GoogleCloudPlatform/google-cloud-java/issues/1740 . private final Level baseLevel; + private final Object writeLock = new Object(); + private final Set> pendingWrites = + Collections.newSetFromMap(new IdentityHashMap, Boolean>()); + /** * Creates an handler that publishes messages to Stackdriver Logging. */ @@ -376,6 +383,9 @@ public void publish(LogRecord record) { if (entry != null) { write(entry, writeOptions); } + if (record.getLevel().intValue() >= flushLevel.intValue()) { + flush(); + } } finally { inPublishCall.remove(); } @@ -457,28 +467,60 @@ void write(LogEntry entry, WriteOption... options) { reportError(null, ex, ErrorManager.FLUSH_FAILURE); } break; + case ASYNC: default: - ApiFutures.addCallback(getLogging().writeAsync(entryList, options), new ApiFutureCallback() { - @Override - public void onSuccess(Void v) {} - - @Override - public void onFailure(Throwable t) { - if (t instanceof Exception) { - reportError(null, (Exception) t, ErrorManager.FLUSH_FAILURE); - } else { - reportError(null, new Exception(t), ErrorManager.FLUSH_FAILURE); - } - } - }); + final ApiFuture writeFuture = getLogging().writeAsync(entryList, options); + synchronized(writeLock) { + pendingWrites.add(writeFuture); + } + ApiFutures.addCallback( + writeFuture, + new ApiFutureCallback() { + private void removeFromPending() { + synchronized(writeLock) { + pendingWrites.remove(writeFuture); + } + } + + @Override + public void onSuccess(Void v) { + removeFromPending(); + } + + @Override + public void onFailure(Throwable t) { + try { + if (t instanceof Exception) { + reportError(null, (Exception) t, ErrorManager.FLUSH_FAILURE); + } else { + reportError(null, new Exception(t), ErrorManager.FLUSH_FAILURE); + } + } finally { + removeFromPending(); + } + } + }); break; } } @Override public void flush() { - // BUG(1795): flush is broken, need support from batching implementation. + // BUG(1795): We should force batcher to issue RPC call for buffered messages, + // so the code below doesn't wait uselessly. + + ArrayList> writesToFlush = new ArrayList<>(); + synchronized(writeLock) { + writesToFlush.addAll(pendingWrites); + } + for (ApiFuture write : writesToFlush) { + try { + Uninterruptibles.getUninterruptibly(write); + } catch (Exception e) { + // Ignore exceptions, they are propagated to the error manager. + } + } } /** diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingOptions.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingOptions.java index 65998d5b0813..feb7cdcacac7 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingOptions.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingOptions.java @@ -34,8 +34,7 @@ public class LoggingOptions extends ServiceOptions { private static final String API_SHORT_NAME = "Logging"; private static final String LOGGING_SCOPE = "https://www.googleapis.com/auth/logging.admin"; private static final Set SCOPES = ImmutableSet.of(LOGGING_SCOPE); - private static final String DEFAULT_HOST = LoggingSettings.getDefaultServiceAddress() - + ':' + LoggingSettings.getDefaultServicePort(); + private static final String DEFAULT_HOST = LoggingSettings.getDefaultEndpoint(); private static final long serialVersionUID = 5753499510627426717L; public static class DefaultLoggingFactory implements LoggingFactory { diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/ConfigClient.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/ConfigClient.java index 4ca4168a1d0c..f188dbc88692 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/ConfigClient.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/ConfigClient.java @@ -29,6 +29,7 @@ import com.google.logging.v2.SinkNameOneof; import com.google.logging.v2.UpdateSinkRequest; import com.google.protobuf.Empty; +import com.google.protobuf.ExperimentalApi; import io.grpc.ManagedChannel; import java.io.Closeable; import java.io.IOException; @@ -94,6 +95,7 @@ * */ @Generated("by GAPIC") +@ExperimentalApi public class ConfigClient implements AutoCloseable { private final ConfigSettings settings; private final ScheduledExecutorService executor; diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/ConfigSettings.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/ConfigSettings.java index af3840601c0d..72fc086723ec 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/ConfigSettings.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/ConfigSettings.java @@ -18,6 +18,7 @@ import static com.google.cloud.logging.spi.v2.PagedResponseWrappers.ListSinksPagedResponse; import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; import com.google.api.gax.core.RetrySettings; import com.google.api.gax.grpc.CallContext; import com.google.api.gax.grpc.ChannelProvider; @@ -80,12 +81,6 @@ @Generated("by GAPIC v0.0.5") @ExperimentalApi public class ConfigSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "logging.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() @@ -99,6 +94,11 @@ public class ConfigSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final PagedCallSettings listSinksSettings; private final SimpleCallSettings getSinkSettings; @@ -137,14 +137,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "logging.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -160,15 +155,18 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = ConfigSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty(ConfigSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/GrpcLoggingRpc.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/GrpcLoggingRpc.java index e7b8ddffb2ad..1ca3155872b2 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/GrpcLoggingRpc.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/GrpcLoggingRpc.java @@ -90,7 +90,8 @@ public GrpcLoggingRpc(LoggingOptions options) throws IOException { .build(); channelProvider = FixedChannelProvider.create(managedChannel); } else { - channelProvider = transportOptions.getChannelProvider(options); + channelProvider = GrpcTransportOptions.setUpChannelProvider( + LoggingSettings.defaultChannelProviderBuilder(), options); } providerManager = ProviderManager.newBuilder() .setChannelProvider(channelProvider) diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/LoggingClient.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/LoggingClient.java index 652b5084353d..17a83d7ee384 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/LoggingClient.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/LoggingClient.java @@ -35,6 +35,7 @@ import com.google.logging.v2.WriteLogEntriesRequest; import com.google.logging.v2.WriteLogEntriesResponse; import com.google.protobuf.Empty; +import com.google.protobuf.ExperimentalApi; import io.grpc.ManagedChannel; import java.io.Closeable; import java.io.IOException; @@ -100,6 +101,7 @@ * */ @Generated("by GAPIC") +@ExperimentalApi public class LoggingClient implements AutoCloseable { private final LoggingSettings settings; private final ScheduledExecutorService executor; diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/LoggingSettings.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/LoggingSettings.java index cad2b49cb166..6199d21d4532 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/LoggingSettings.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/LoggingSettings.java @@ -21,10 +21,12 @@ import com.google.api.MonitoredResourceDescriptor; import com.google.api.gax.batching.BatchingSettings; +import com.google.api.gax.batching.PartitionKey; import com.google.api.gax.batching.RequestBuilder; import com.google.api.gax.core.FlowControlSettings; import com.google.api.gax.core.FlowController.LimitExceededBehavior; import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; import com.google.api.gax.core.RetrySettings; import com.google.api.gax.grpc.BatchedRequestIssuer; import com.google.api.gax.grpc.BatchingCallSettings; @@ -94,12 +96,6 @@ @Generated("by GAPIC v0.0.5") @ExperimentalApi public class LoggingSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "logging.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() @@ -113,6 +109,11 @@ public class LoggingSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final SimpleCallSettings deleteLogSettings; private final BatchingCallSettings writeLogEntriesSettings; @@ -163,14 +164,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "logging.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -186,15 +182,18 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = LoggingSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty(LoggingSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ @@ -389,13 +388,9 @@ public ListLogsPagedResponse createPagedListResponse( WRITE_LOG_ENTRIES_BATCHING_DESC = new BatchingDescriptor() { @Override - public String getBatchPartitionKey(WriteLogEntriesRequest request) { - return request.getLogName() - + "|" - + request.getResource() - + "|" - + request.getLabels() - + "|"; + public PartitionKey getBatchPartitionKey(WriteLogEntriesRequest request) { + return new PartitionKey( + request.getLogName(), request.getResource(), request.getLabels()); } @Override diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/MetricsClient.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/MetricsClient.java index e76ab3eb110d..af0aeb7cb9e9 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/MetricsClient.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/MetricsClient.java @@ -29,6 +29,7 @@ import com.google.logging.v2.ParentNameOneof; import com.google.logging.v2.UpdateLogMetricRequest; import com.google.protobuf.Empty; +import com.google.protobuf.ExperimentalApi; import io.grpc.ManagedChannel; import java.io.Closeable; import java.io.IOException; @@ -93,6 +94,7 @@ * */ @Generated("by GAPIC") +@ExperimentalApi public class MetricsClient implements AutoCloseable { private final MetricsSettings settings; private final ScheduledExecutorService executor; diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/MetricsSettings.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/MetricsSettings.java index b13a1d0091d2..7606629adbe7 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/MetricsSettings.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/MetricsSettings.java @@ -18,6 +18,7 @@ import static com.google.cloud.logging.spi.v2.PagedResponseWrappers.ListLogMetricsPagedResponse; import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; import com.google.api.gax.core.RetrySettings; import com.google.api.gax.grpc.CallContext; import com.google.api.gax.grpc.ChannelProvider; @@ -80,12 +81,6 @@ @Generated("by GAPIC v0.0.5") @ExperimentalApi public class MetricsSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "logging.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() @@ -99,6 +94,11 @@ public class MetricsSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final PagedCallSettings< ListLogMetricsRequest, ListLogMetricsResponse, ListLogMetricsPagedResponse> listLogMetricsSettings; @@ -139,14 +139,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "logging.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -162,15 +157,18 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = MetricsSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty(MetricsSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/LoggingHandlerTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/LoggingHandlerTest.java index 7ac494013234..a9d31cbc726e 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/LoggingHandlerTest.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/LoggingHandlerTest.java @@ -18,8 +18,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; import com.google.api.gax.core.ApiFutures; +import com.google.api.gax.core.SettableApiFuture; import com.google.cloud.MonitoredResource; import com.google.cloud.logging.LogEntry.Builder; import com.google.cloud.logging.Logging.WriteOption; @@ -380,6 +383,41 @@ public void testFlushLevel() { handler.publish(newLogRecord(Level.WARNING, MESSAGE)); } + @Test + public void testFlush() throws InterruptedException { + final SettableApiFuture mockRpc = SettableApiFuture.create(); + + EasyMock.expect(options.getProjectId()).andReturn(PROJECT).anyTimes(); + EasyMock.expect(options.getService()).andReturn(logging); + logging.writeAsync(ImmutableList.of(INFO_ENTRY), DEFAULT_OPTIONS); + EasyMock.expectLastCall().andReturn(mockRpc); + EasyMock.replay(options, logging); + final LoggingHandler handler = new LoggingHandler(LOG_NAME, options); + handler.setFormatter(new TestFormatter()); + + // no messages, nothing to flush. + handler.flush(); + + // send a message + handler.publish(newLogRecord(Level.INFO, MESSAGE)); + Thread flushWaiter = new Thread(new Runnable() { + @Override + public void run() { + handler.flush(); + } + }); + flushWaiter.start(); + + // flushWaiter should be waiting for mockRpc to complete. + flushWaiter.join(1000); + assertTrue(flushWaiter.isAlive()); + + // With the RPC completed, flush should return, and the thread should terminate. + mockRpc.set(null); + flushWaiter.join(1000); + assertFalse(flushWaiter.isAlive()); + } + @Test public void testSyncWrite() { EasyMock.expect(options.getProjectId()).andReturn(PROJECT).anyTimes(); diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/spi/v2/ConfigClientTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/spi/v2/ConfigClientTest.java index f4be97134428..8d9bbcef1888 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/spi/v2/ConfigClientTest.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/spi/v2/ConfigClientTest.java @@ -116,7 +116,7 @@ public void listSinksTest() { @Test @SuppressWarnings("all") public void listSinksExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockConfigServiceV2.addException(exception); try { @@ -125,7 +125,7 @@ public void listSinksExceptionTest() throws Exception { client.listSinks(parent); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -160,7 +160,7 @@ public void getSinkTest() { @Test @SuppressWarnings("all") public void getSinkExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockConfigServiceV2.addException(exception); try { @@ -169,7 +169,7 @@ public void getSinkExceptionTest() throws Exception { client.getSink(sinkName); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -206,7 +206,7 @@ public void createSinkTest() { @Test @SuppressWarnings("all") public void createSinkExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockConfigServiceV2.addException(exception); try { @@ -216,7 +216,7 @@ public void createSinkExceptionTest() throws Exception { client.createSink(parent, sink); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -253,7 +253,7 @@ public void updateSinkTest() { @Test @SuppressWarnings("all") public void updateSinkExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockConfigServiceV2.addException(exception); try { @@ -263,7 +263,7 @@ public void updateSinkExceptionTest() throws Exception { client.updateSink(sinkName, sink); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -287,7 +287,7 @@ public void deleteSinkTest() { @Test @SuppressWarnings("all") public void deleteSinkExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockConfigServiceV2.addException(exception); try { @@ -296,7 +296,7 @@ public void deleteSinkExceptionTest() throws Exception { client.deleteSink(sinkName); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } } diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/spi/v2/LoggingClientTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/spi/v2/LoggingClientTest.java index 0b3cb1201954..639ba66957a7 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/spi/v2/LoggingClientTest.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/spi/v2/LoggingClientTest.java @@ -113,7 +113,7 @@ public void deleteLogTest() { @Test @SuppressWarnings("all") public void deleteLogExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockLoggingServiceV2.addException(exception); try { @@ -122,7 +122,7 @@ public void deleteLogExceptionTest() throws Exception { client.deleteLog(logName); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -154,7 +154,7 @@ public void writeLogEntriesTest() { @Test @SuppressWarnings("all") public void writeLogEntriesExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockLoggingServiceV2.addException(exception); try { @@ -166,7 +166,7 @@ public void writeLogEntriesExceptionTest() throws Exception { client.writeLogEntries(logName, resource, labels, entries); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -206,7 +206,7 @@ public void listLogEntriesTest() { @Test @SuppressWarnings("all") public void listLogEntriesExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockLoggingServiceV2.addException(exception); try { @@ -217,7 +217,7 @@ public void listLogEntriesExceptionTest() throws Exception { client.listLogEntries(resourceNames, filter, orderBy); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -252,7 +252,7 @@ public void listLogsTest() { @Test @SuppressWarnings("all") public void listLogsExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockLoggingServiceV2.addException(exception); try { @@ -261,7 +261,7 @@ public void listLogsExceptionTest() throws Exception { client.listLogs(parent); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } } diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/spi/v2/MetricsClientTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/spi/v2/MetricsClientTest.java index cba811a96f69..d8955b76f1c2 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/spi/v2/MetricsClientTest.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/spi/v2/MetricsClientTest.java @@ -118,7 +118,7 @@ public void listLogMetricsTest() { @Test @SuppressWarnings("all") public void listLogMetricsExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockMetricsServiceV2.addException(exception); try { @@ -127,7 +127,7 @@ public void listLogMetricsExceptionTest() throws Exception { client.listLogMetrics(parent); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -156,7 +156,7 @@ public void getLogMetricTest() { @Test @SuppressWarnings("all") public void getLogMetricExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockMetricsServiceV2.addException(exception); try { @@ -165,7 +165,7 @@ public void getLogMetricExceptionTest() throws Exception { client.getLogMetric(metricName); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -196,7 +196,7 @@ public void createLogMetricTest() { @Test @SuppressWarnings("all") public void createLogMetricExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockMetricsServiceV2.addException(exception); try { @@ -206,7 +206,7 @@ public void createLogMetricExceptionTest() throws Exception { client.createLogMetric(parent, metric); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -237,7 +237,7 @@ public void updateLogMetricTest() { @Test @SuppressWarnings("all") public void updateLogMetricExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockMetricsServiceV2.addException(exception); try { @@ -247,7 +247,7 @@ public void updateLogMetricExceptionTest() throws Exception { client.updateLogMetric(metricName, metric); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -271,7 +271,7 @@ public void deleteLogMetricTest() { @Test @SuppressWarnings("all") public void deleteLogMetricExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockMetricsServiceV2.addException(exception); try { @@ -280,7 +280,7 @@ public void deleteLogMetricExceptionTest() throws Exception { client.deleteLogMetric(metricName); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } } diff --git a/google-cloud-monitoring/pom.xml b/google-cloud-monitoring/pom.xml index d0f602a79afd..156f95ba0124 100644 --- a/google-cloud-monitoring/pom.xml +++ b/google-cloud-monitoring/pom.xml @@ -11,10 +11,11 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-monitoring + ${project.version} @@ -87,6 +88,22 @@ + + org.codehaus.mojo + properties-maven-plugin + 1.0-alpha-2 + + + generate-resources + + write-project-properties + + + ${project.build.outputDirectory}/project.properties + + + + org.codehaus.mojo build-helper-maven-plugin diff --git a/google-cloud-monitoring/src/main/java/com/google/cloud/monitoring/spi/v3/GroupServiceSettings.java b/google-cloud-monitoring/src/main/java/com/google/cloud/monitoring/spi/v3/GroupServiceSettings.java index 2cb0b3cee250..efcf63783b42 100644 --- a/google-cloud-monitoring/src/main/java/com/google/cloud/monitoring/spi/v3/GroupServiceSettings.java +++ b/google-cloud-monitoring/src/main/java/com/google/cloud/monitoring/spi/v3/GroupServiceSettings.java @@ -20,6 +20,7 @@ import com.google.api.MonitoredResource; import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; import com.google.api.gax.core.RetrySettings; import com.google.api.gax.grpc.CallContext; import com.google.api.gax.grpc.ChannelProvider; @@ -84,12 +85,6 @@ @Generated("by GAPIC v0.0.5") @ExperimentalApi public class GroupServiceSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "monitoring.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() @@ -102,6 +97,11 @@ public class GroupServiceSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final PagedCallSettings listGroupsSettings; private final SimpleCallSettings getGroupSettings; @@ -150,14 +150,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "monitoring.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -173,15 +168,19 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = GroupServiceSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty( + GroupServiceSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ diff --git a/google-cloud-monitoring/src/main/java/com/google/cloud/monitoring/spi/v3/MetricServiceSettings.java b/google-cloud-monitoring/src/main/java/com/google/cloud/monitoring/spi/v3/MetricServiceSettings.java index 4ac50798b982..cb549bc18ed7 100644 --- a/google-cloud-monitoring/src/main/java/com/google/cloud/monitoring/spi/v3/MetricServiceSettings.java +++ b/google-cloud-monitoring/src/main/java/com/google/cloud/monitoring/spi/v3/MetricServiceSettings.java @@ -22,6 +22,7 @@ import com.google.api.MetricDescriptor; import com.google.api.MonitoredResourceDescriptor; import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; import com.google.api.gax.core.RetrySettings; import com.google.api.gax.grpc.CallContext; import com.google.api.gax.grpc.ChannelProvider; @@ -89,12 +90,6 @@ @Generated("by GAPIC v0.0.5") @ExperimentalApi public class MetricServiceSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "monitoring.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() @@ -107,6 +102,11 @@ public class MetricServiceSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final PagedCallSettings< ListMonitoredResourceDescriptorsRequest, ListMonitoredResourceDescriptorsResponse, ListMonitoredResourceDescriptorsPagedResponse> @@ -185,14 +185,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "monitoring.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -208,15 +203,19 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = MetricServiceSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty( + MetricServiceSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ diff --git a/google-cloud-monitoring/src/test/java/com/google/cloud/monitoring/spi/v3/GroupServiceClientTest.java b/google-cloud-monitoring/src/test/java/com/google/cloud/monitoring/spi/v3/GroupServiceClientTest.java index bcdffb6ec8de..e145ebba9a9a 100644 --- a/google-cloud-monitoring/src/test/java/com/google/cloud/monitoring/spi/v3/GroupServiceClientTest.java +++ b/google-cloud-monitoring/src/test/java/com/google/cloud/monitoring/spi/v3/GroupServiceClientTest.java @@ -115,7 +115,7 @@ public void getGroupTest() { @Test @SuppressWarnings("all") public void getGroupExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockGroupService.addException(exception); try { @@ -124,7 +124,7 @@ public void getGroupExceptionTest() throws Exception { client.getGroup(name); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -163,7 +163,7 @@ public void createGroupTest() { @Test @SuppressWarnings("all") public void createGroupExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockGroupService.addException(exception); try { @@ -173,7 +173,7 @@ public void createGroupExceptionTest() throws Exception { client.createGroup(name, group); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -210,7 +210,7 @@ public void updateGroupTest() { @Test @SuppressWarnings("all") public void updateGroupExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockGroupService.addException(exception); try { @@ -219,7 +219,7 @@ public void updateGroupExceptionTest() throws Exception { client.updateGroup(group); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -243,7 +243,7 @@ public void deleteGroupTest() { @Test @SuppressWarnings("all") public void deleteGroupExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockGroupService.addException(exception); try { @@ -252,7 +252,7 @@ public void deleteGroupExceptionTest() throws Exception { client.deleteGroup(name); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -289,7 +289,7 @@ public void listGroupMembersTest() { @Test @SuppressWarnings("all") public void listGroupMembersExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockGroupService.addException(exception); try { @@ -298,7 +298,7 @@ public void listGroupMembersExceptionTest() throws Exception { client.listGroupMembers(name); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } } diff --git a/google-cloud-monitoring/src/test/java/com/google/cloud/monitoring/spi/v3/MetricServiceClientTest.java b/google-cloud-monitoring/src/test/java/com/google/cloud/monitoring/spi/v3/MetricServiceClientTest.java index ae649f904be1..b6d3f705d14a 100644 --- a/google-cloud-monitoring/src/test/java/com/google/cloud/monitoring/spi/v3/MetricServiceClientTest.java +++ b/google-cloud-monitoring/src/test/java/com/google/cloud/monitoring/spi/v3/MetricServiceClientTest.java @@ -130,7 +130,7 @@ public void listMonitoredResourceDescriptorsTest() { @Test @SuppressWarnings("all") public void listMonitoredResourceDescriptorsExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockMetricService.addException(exception); try { @@ -139,7 +139,7 @@ public void listMonitoredResourceDescriptorsExceptionTest() throws Exception { client.listMonitoredResourceDescriptors(name); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -176,7 +176,7 @@ public void getMonitoredResourceDescriptorTest() { @Test @SuppressWarnings("all") public void getMonitoredResourceDescriptorExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockMetricService.addException(exception); try { @@ -186,7 +186,7 @@ public void getMonitoredResourceDescriptorExceptionTest() throws Exception { client.getMonitoredResourceDescriptor(name); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -222,7 +222,7 @@ public void listMetricDescriptorsTest() { @Test @SuppressWarnings("all") public void listMetricDescriptorsExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockMetricService.addException(exception); try { @@ -231,7 +231,7 @@ public void listMetricDescriptorsExceptionTest() throws Exception { client.listMetricDescriptors(name); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -268,7 +268,7 @@ public void getMetricDescriptorTest() { @Test @SuppressWarnings("all") public void getMetricDescriptorExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockMetricService.addException(exception); try { @@ -277,7 +277,7 @@ public void getMetricDescriptorExceptionTest() throws Exception { client.getMetricDescriptor(name); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -317,7 +317,7 @@ public void createMetricDescriptorTest() { @Test @SuppressWarnings("all") public void createMetricDescriptorExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockMetricService.addException(exception); try { @@ -327,7 +327,7 @@ public void createMetricDescriptorExceptionTest() throws Exception { client.createMetricDescriptor(name, metricDescriptor); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -352,7 +352,7 @@ public void deleteMetricDescriptorTest() { @Test @SuppressWarnings("all") public void deleteMetricDescriptorExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockMetricService.addException(exception); try { @@ -361,7 +361,7 @@ public void deleteMetricDescriptorExceptionTest() throws Exception { client.deleteMetricDescriptor(name); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -403,7 +403,7 @@ public void listTimeSeriesTest() { @Test @SuppressWarnings("all") public void listTimeSeriesExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockMetricService.addException(exception); try { @@ -415,7 +415,7 @@ public void listTimeSeriesExceptionTest() throws Exception { client.listTimeSeries(name, filter, interval, view); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -441,7 +441,7 @@ public void createTimeSeriesTest() { @Test @SuppressWarnings("all") public void createTimeSeriesExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockMetricService.addException(exception); try { @@ -451,7 +451,7 @@ public void createTimeSeriesExceptionTest() throws Exception { client.createTimeSeries(name, timeSeries); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } } diff --git a/google-cloud-pubsub/README.md b/google-cloud-pubsub/README.md index e78aa3fca62f..2dac9d0d8ef8 100644 --- a/google-cloud-pubsub/README.md +++ b/google-cloud-pubsub/README.md @@ -26,16 +26,16 @@ Add this to your pom.xml file com.google.cloud google-cloud-pubsub - 0.10.0-alpha + 0.12.0-alpha ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-pubsub:0.10.0-alpha' +compile 'com.google.cloud:google-cloud-pubsub:0.12.0-alpha' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-pubsub" % "0.10.0-alpha" +libraryDependencies += "com.google.cloud" % "google-cloud-pubsub" % "0.12.0-alpha" ``` Example Application @@ -95,15 +95,15 @@ With Pub/Sub you can create topics. A topic is a named resource to which message publishers. Add the following imports at the top of your file: ```java -import com.google.cloud.pubsub.spi.v1.PublisherClient; +import com.google.cloud.pubsub.spi.v1.TopicAdminClient; import com.google.pubsub.v1.TopicName; ``` Then, to create the topic, use the following code: ```java TopicName topic = TopicName.create("test-project", "test-topic"); -try (PublisherClient publisherClient = PublisherClient.create()) { - publisherClient.createTopic(topic); +try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + topicAdminClient.createTopic(topic); } ``` @@ -137,7 +137,7 @@ With Pub/Sub you can create subscriptions. A subscription represents the stream single, specific topic. Add the following imports at the top of your file: ```java -import com.google.cloud.pubsub.spi.v1.SubscriberClient; +import com.google.cloud.pubsub.spi.v1.SubscriptionAdminClient; import com.google.pubsub.v1.PushConfig; import com.google.pubsub.v1.SubscriptionName; import com.google.pubsub.v1.TopicName; @@ -148,8 +148,8 @@ Then, to create the subscription, use the following code: TopicName topic = TopicName.create("test-project", "test-topic"); SubscriptionName subscription = SubscriptionName.create("test-project", "test-subscription"); -try (SubscriberClient subscriberClient = SubscriberClient.create()) { - subscriberClient.createSubscription(subscription, topic, PushConfig.getDefaultInstance(), 0); +try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) { + subscriptionAdminClient.createSubscription(subscription, topic, PushConfig.getDefaultInstance(), 0); } ``` diff --git a/google-cloud-pubsub/pom.xml b/google-cloud-pubsub/pom.xml index 633bf4e8659a..466bcc8f216e 100644 --- a/google-cloud-pubsub/pom.xml +++ b/google-cloud-pubsub/pom.xml @@ -11,10 +11,11 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-pubsub + ${project.version} @@ -30,7 +31,7 @@ com.google.api.grpc grpc-google-cloud-pubsub-v1 - 0.1.5 + 0.1.6 io.grpc @@ -93,6 +94,22 @@ + + org.codehaus.mojo + properties-maven-plugin + 1.0-alpha-2 + + + generate-resources + + write-project-properties + + + ${project.build.outputDirectory}/project.properties + + + + org.codehaus.mojo build-helper-maven-plugin diff --git a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PagedResponseWrappers.java b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PagedResponseWrappers.java index 56c37d765e47..09a450592ae3 100644 --- a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PagedResponseWrappers.java +++ b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PagedResponseWrappers.java @@ -22,12 +22,15 @@ import com.google.common.base.Function; import com.google.common.collect.Iterables; import com.google.protobuf.ExperimentalApi; +import com.google.pubsub.v1.ListSnapshotsRequest; +import com.google.pubsub.v1.ListSnapshotsResponse; import com.google.pubsub.v1.ListSubscriptionsRequest; import com.google.pubsub.v1.ListSubscriptionsResponse; import com.google.pubsub.v1.ListTopicSubscriptionsRequest; import com.google.pubsub.v1.ListTopicSubscriptionsResponse; import com.google.pubsub.v1.ListTopicsRequest; import com.google.pubsub.v1.ListTopicsResponse; +import com.google.pubsub.v1.Snapshot; import com.google.pubsub.v1.Subscription; import com.google.pubsub.v1.SubscriptionName; import com.google.pubsub.v1.Topic; @@ -93,4 +96,16 @@ public ListSubscriptionsPagedResponse( super(callable, pageDescriptor, request, context); } } + + public static class ListSnapshotsPagedResponse + extends PagedListResponseImpl { + + public ListSnapshotsPagedResponse( + UnaryCallable callable, + PagedListDescriptor pageDescriptor, + ListSnapshotsRequest request, + CallContext context) { + super(callable, pageDescriptor, request, context); + } + } } diff --git a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PollingSubscriberConnection.java b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PollingSubscriberConnection.java index 91acca40cf08..5f979490979a 100644 --- a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PollingSubscriberConnection.java +++ b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PollingSubscriberConnection.java @@ -16,14 +16,14 @@ package com.google.cloud.pubsub.spi.v1; -import com.google.api.gax.core.FlowController; +import com.google.api.gax.core.AbstractApiService; import com.google.api.gax.core.ApiClock; +import com.google.api.gax.core.FlowController; import com.google.api.stats.Distribution; import com.google.auth.Credentials; import com.google.cloud.pubsub.spi.v1.MessageDispatcher.AckProcessor; import com.google.cloud.pubsub.spi.v1.MessageDispatcher.PendingModifyAckDeadline; import com.google.common.collect.Lists; -import com.google.common.util.concurrent.AbstractService; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -45,10 +45,9 @@ import org.joda.time.Duration; /** - * Implementation of {@link AckProcessor} based on Cloud Pub/Sub pull and - * acknowledge operations. + * Implementation of {@link AckProcessor} based on Cloud Pub/Sub pull and acknowledge operations. */ -final class PollingSubscriberConnection extends AbstractService implements AckProcessor { +final class PollingSubscriberConnection extends AbstractApiService implements AckProcessor { private static final int MAX_PER_REQUEST_CHANGES = 1000; private static final Duration DEFAULT_TIMEOUT = Duration.standardSeconds(10); private static final int DEFAULT_MAX_MESSAGES = 1000; diff --git a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/Publisher.java b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/Publisher.java index ddcfa9d8522e..96f7a5ae5ad9 100644 --- a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/Publisher.java +++ b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/Publisher.java @@ -509,7 +509,7 @@ interface LongRandom { * String projectName = "my_project"; * String topicName = "my_topic"; * TopicName topic = TopicName.create(projectName, topicName); - * Publisher publisher = Publisher.newBuilder(topic).build(); + * Publisher publisher = Publisher.defaultBuilder(topic).build(); * try { * // ... * } finally { @@ -519,7 +519,7 @@ interface LongRandom { * } * */ - public static Builder newBuilder(TopicName topicName) { + public static Builder defaultBuilder(TopicName topicName) { return new Builder(topicName); } @@ -575,7 +575,7 @@ public long nextLong(long least, long bound) { RetrySettings retrySettings = DEFAULT_RETRY_SETTINGS; LongRandom longRandom = DEFAULT_LONG_RANDOM; - ChannelProvider channelProvider = PublisherSettings.defaultChannelProviderBuilder().build(); + ChannelProvider channelProvider = TopicAdminSettings.defaultChannelProviderBuilder().build(); ExecutorProvider executorProvider = DEFAULT_EXECUTOR_PROVIDER; private Builder(TopicName topic) { diff --git a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/StreamingSubscriberConnection.java b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/StreamingSubscriberConnection.java index 1bb06cf9b341..a85fad6b0cce 100644 --- a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/StreamingSubscriberConnection.java +++ b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/StreamingSubscriberConnection.java @@ -16,15 +16,15 @@ package com.google.cloud.pubsub.spi.v1; -import com.google.api.gax.core.FlowController; +import com.google.api.gax.core.AbstractApiService; import com.google.api.gax.core.ApiClock; +import com.google.api.gax.core.FlowController; import com.google.api.stats.Distribution; import com.google.auth.Credentials; import com.google.cloud.pubsub.spi.v1.MessageDispatcher.AckProcessor; import com.google.cloud.pubsub.spi.v1.MessageDispatcher.PendingModifyAckDeadline; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; -import com.google.common.util.concurrent.AbstractService; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.SettableFuture; @@ -48,7 +48,7 @@ import org.joda.time.Duration; /** Implementation of {@link AckProcessor} based on Cloud Pub/Sub streaming pull. */ -final class StreamingSubscriberConnection extends AbstractService implements AckProcessor { +final class StreamingSubscriberConnection extends AbstractApiService implements AckProcessor { private static final Logger logger = Logger.getLogger(StreamingSubscriberConnection.class.getName()); diff --git a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/Subscriber.java b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/Subscriber.java index 32978fd1be18..f46c5eb349c1 100644 --- a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/Subscriber.java +++ b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/Subscriber.java @@ -16,10 +16,12 @@ package com.google.cloud.pubsub.spi.v1; +import com.google.api.gax.core.AbstractApiService; +import com.google.api.gax.core.ApiClock; +import com.google.api.gax.core.ApiService; import com.google.api.gax.core.CurrentMillisClock; import com.google.api.gax.core.FlowControlSettings; import com.google.api.gax.core.FlowController; -import com.google.api.gax.core.ApiClock;; import com.google.api.gax.grpc.ExecutorProvider; import com.google.api.gax.grpc.InstantiatingExecutorProvider; import com.google.api.stats.Distribution; @@ -29,8 +31,6 @@ import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.primitives.Ints; -import com.google.common.util.concurrent.AbstractService; -import com.google.common.util.concurrent.Service; import com.google.pubsub.v1.SubscriptionName; import io.grpc.ManagedChannelBuilder; import io.grpc.Status; @@ -42,11 +42,9 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.logging.Level; import java.util.logging.Logger; import org.joda.time.Duration; @@ -77,7 +75,7 @@ *

    If no credentials are provided, the {@link Subscriber} will use application default * credentials through {@link GoogleCredentials#getApplicationDefault}. */ -public class Subscriber { +public class Subscriber extends AbstractApiService { private static final int THREADS_PER_CHANNEL = 5; @VisibleForTesting static final int CHANNELS_PER_CORE = 10; private static final int MAX_INBOUND_MESSAGE_SIZE = @@ -88,10 +86,77 @@ public class Subscriber { private static final Duration ACK_DEADLINE_UPDATE_PERIOD = Duration.standardMinutes(1); private static final double PERCENTILE_FOR_ACK_DEADLINE_UPDATES = 99.9; - private final SubscriberImpl impl; + private static final Logger logger = Logger.getLogger(Subscriber.class.getName()); + + private final SubscriptionName subscriptionName; + private final String cachedSubscriptionNameString; + private final FlowControlSettings flowControlSettings; + private final Duration ackExpirationPadding; + private final ScheduledExecutorService executor; + private final Distribution ackLatencyDistribution = + new Distribution(MAX_ACK_DEADLINE_SECONDS + 1); + private final int numChannels; + private final FlowController flowController; + private final ManagedChannelBuilder> channelBuilder; + private final Credentials credentials; + private final MessageReceiver receiver; + private final List streamingSubscriberConnections; + private final List pollingSubscriberConnections; + private final ApiClock clock; + private final List closeables = new ArrayList<>(); + private ScheduledFuture ackDeadlineUpdater; + private int streamAckDeadlineSeconds; private Subscriber(Builder builder) throws IOException { - impl = new SubscriberImpl(builder); + receiver = builder.receiver; + flowControlSettings = builder.flowControlSettings; + subscriptionName = builder.subscriptionName; + cachedSubscriptionNameString = subscriptionName.toString(); + ackExpirationPadding = builder.ackExpirationPadding; + streamAckDeadlineSeconds = + Math.max( + INITIAL_ACK_DEADLINE_SECONDS, + Ints.saturatedCast(ackExpirationPadding.getStandardSeconds())); + clock = builder.clock.isPresent() ? builder.clock.get() : CurrentMillisClock.getDefaultClock(); + + flowController = new FlowController(builder.flowControlSettings); + + executor = builder.executorProvider.getExecutor(); + if (builder.executorProvider.shouldAutoClose()) { + closeables.add( + new AutoCloseable() { + @Override + public void close() throws IOException { + executor.shutdown(); + } + }); + } + + // TODO(pongad): remove this when we move to ManagedChannelBuilder + String defaultEndpoint = SubscriptionAdminSettings.getDefaultEndpoint(); + int colonPos = defaultEndpoint.indexOf(':'); + + channelBuilder = + builder.channelBuilder.isPresent() + ? builder.channelBuilder.get() + : NettyChannelBuilder.forAddress( + defaultEndpoint.substring(0, colonPos), + Integer.parseInt(defaultEndpoint.substring(colonPos+1))) + .maxMessageSize(MAX_INBOUND_MESSAGE_SIZE) + .flowControlWindow(5000000) // 2.5 MB + .negotiationType(NegotiationType.TLS) + .sslContext(GrpcSslContexts.forClient().ciphers(null).build()) + .executor(executor); + + credentials = + builder.credentials.isPresent() + ? builder.credentials.get() + : GoogleCredentials.getApplicationDefault() + .createScoped(SubscriptionAdminSettings.getDefaultServiceScopes()); + + numChannels = Math.max(1, Runtime.getRuntime().availableProcessors()) * CHANNELS_PER_CORE; + streamingSubscriberConnections = new ArrayList(numChannels); + pollingSubscriberConnections = new ArrayList(numChannels); } /** @@ -104,78 +169,23 @@ private Subscriber(Builder builder) throws IOException { * @param receiver an implementation of {@link MessageReceiver} used to process the received * messages */ - public static Builder newBuilder(SubscriptionName subscription, MessageReceiver receiver) { + public static Builder defaultBuilder(SubscriptionName subscription, MessageReceiver receiver) { return new Builder(subscription, receiver); } /** Subscription which the subscriber is subscribed to. */ public SubscriptionName getSubscriptionName() { - return impl.subscriptionName; + return subscriptionName; } /** Acknowledgement expiration padding. See {@link Builder#setAckExpirationPadding}. */ public Duration getAckExpirationPadding() { - return impl.ackExpirationPadding; + return ackExpirationPadding; } /** The flow control settings the Subscriber is configured with. */ public FlowControlSettings getFlowControlSettings() { - return impl.flowControlSettings; - } - - public void addListener(final SubscriberListener listener, Executor executor) { - impl.addListener( - new Service.Listener() { - @Override - public void failed(Service.State from, Throwable failure) { - listener.failed(convertState(from), failure); - } - - @Override - public void running() { - listener.running(); - } - - @Override - public void starting() { - listener.starting(); - } - - @Override - public void stopping(Service.State from) { - listener.stopping(convertState(from)); - } - - @Override - public void terminated(Service.State from) { - listener.terminated(convertState(from)); - } - }, - executor); - } - - public void awaitRunning() { - impl.awaitRunning(); - } - - public void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException { - impl.awaitRunning(timeout, unit); - } - - public void awaitTerminated() { - impl.awaitTerminated(); - } - - public void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException { - impl.awaitTerminated(timeout, unit); - } - - public Throwable failureCause() { - return impl.failureCause(); - } - - public boolean isRunning() { - return impl.isRunning(); + return flowControlSettings; } /** @@ -183,8 +193,8 @@ public boolean isRunning() { * *

    Example of receiving a specific number of messages. *

     {@code
    -   * Subscriber subscriber = Subscriber.newBuilder(subscription, receiver).build();
    -   * subscriber.addListener(new Subscriber.SubscriberListener() {
    +   * Subscriber subscriber = Subscriber.defaultBuilder(subscription, receiver).build();
    +   * subscriber.addListener(new Subscriber.Listener() {
        *   public void failed(Subscriber.State from, Throwable failure) {
        *     // Handle error.
        *   }
    @@ -197,319 +207,201 @@ public boolean isRunning() {
        * }
    * */ - public Subscriber startAsync() { - impl.startAsync(); - return this; - } - - public State state() { - return convertState(impl.state()); + @Override + public ApiService startAsync() { + // Override only for the docs. + return super.startAsync(); } - private State convertState(Service.State state) { - switch (state) { - case FAILED: - return State.FAILED; - case NEW: - return State.NEW; - case RUNNING: - return State.RUNNING; - case STARTING: - return State.STARTING; - case STOPPING: - return State.STOPPING; - case TERMINATED: - return State.TERMINATED; - } - throw new IllegalStateException("unknown state: " + state); + @Override + protected void doStart() { + logger.log(Level.FINE, "Starting subscriber group."); + // Streaming pull is not enabled on the service yet. + // startStreamingConnections(); + startPollingConnections(); + notifyStarted(); } - public Subscriber stopAsync() { - impl.stopAsync(); - return this; - } - - public enum State { - FAILED, - NEW, - RUNNING, - STARTING, - STOPPING, - TERMINATED - } - - public abstract static class SubscriberListener { - public void failed(Subscriber.State from, Throwable failure) {} - - public void running() {} - - public void starting() {} - - public void stopping(State from) {} - - public void terminated(State from) {} - } - - private static class SubscriberImpl extends AbstractService { - private static final Logger logger = Logger.getLogger(Subscriber.class.getName()); - - private final SubscriptionName subscriptionName; - private final String cachedSubscriptionNameString; - private final FlowControlSettings flowControlSettings; - private final Duration ackExpirationPadding; - private final ScheduledExecutorService executor; - private final Distribution ackLatencyDistribution = - new Distribution(MAX_ACK_DEADLINE_SECONDS + 1); - private final int numChannels; - private final FlowController flowController; - private final ManagedChannelBuilder> channelBuilder; - private final Credentials credentials; - private final MessageReceiver receiver; - private final List streamingSubscriberConnections; - private final List pollingSubscriberConnections; - private final ApiClock clock; - private final List closeables = new ArrayList<>(); - private ScheduledFuture ackDeadlineUpdater; - private int streamAckDeadlineSeconds; - - private SubscriberImpl(Builder builder) throws IOException { - receiver = builder.receiver; - flowControlSettings = builder.flowControlSettings; - subscriptionName = builder.subscriptionName; - cachedSubscriptionNameString = subscriptionName.toString(); - ackExpirationPadding = builder.ackExpirationPadding; - streamAckDeadlineSeconds = - Math.max( - INITIAL_ACK_DEADLINE_SECONDS, - Ints.saturatedCast(ackExpirationPadding.getStandardSeconds())); - clock = builder.clock.isPresent() ? builder.clock.get() : CurrentMillisClock.getDefaultClock(); - - flowController = new FlowController(builder.flowControlSettings); - - executor = builder.executorProvider.getExecutor(); - if (builder.executorProvider.shouldAutoClose()) { - closeables.add( - new AutoCloseable() { - @Override - public void close() throws IOException { - executor.shutdown(); - } - }); + @Override + protected void doStop() { + stopAllStreamingConnections(); + stopAllPollingConnections(); + try { + for (AutoCloseable closeable : closeables) { + closeable.close(); } - - channelBuilder = - builder.channelBuilder.isPresent() - ? builder.channelBuilder.get() - : NettyChannelBuilder.forAddress( - SubscriberSettings.getDefaultServiceAddress(), - SubscriberSettings.getDefaultServicePort()) - .maxMessageSize(MAX_INBOUND_MESSAGE_SIZE) - .flowControlWindow(5000000) // 2.5 MB - .negotiationType(NegotiationType.TLS) - .sslContext(GrpcSslContexts.forClient().ciphers(null).build()) - .executor(executor); - - credentials = - builder.credentials.isPresent() - ? builder.credentials.get() - : GoogleCredentials.getApplicationDefault() - .createScoped(SubscriberSettings.getDefaultServiceScopes()); - - numChannels = Math.max(1, Runtime.getRuntime().availableProcessors()) * CHANNELS_PER_CORE; - streamingSubscriberConnections = new ArrayList(numChannels); - pollingSubscriberConnections = new ArrayList(numChannels); - } - - @Override - protected void doStart() { - logger.log(Level.FINE, "Starting subscriber group."); - // Streaming pull is not enabled on the service yet. - // startStreamingConnections(); - startPollingConnections(); - notifyStarted(); + notifyStopped(); + } catch (Exception e) { + notifyFailed(e); } + } - @Override - protected void doStop() { - stopAllStreamingConnections(); - stopAllPollingConnections(); - try { - for (AutoCloseable closeable : closeables) { - closeable.close(); - } - notifyStopped(); - } catch (Exception e) { - notifyFailed(e); + private void startStreamingConnections() { + synchronized (streamingSubscriberConnections) { + for (int i = 0; i < numChannels; i++) { + streamingSubscriberConnections.add( + new StreamingSubscriberConnection( + cachedSubscriptionNameString, + credentials, + receiver, + ackExpirationPadding, + streamAckDeadlineSeconds, + ackLatencyDistribution, + channelBuilder.build(), + flowController, + executor, + clock)); } + startConnections( + streamingSubscriberConnections, + new Listener() { + @Override + public void failed(State from, Throwable failure) { + // If a connection failed is because of a fatal error, we should fail the + // whole subscriber. + stopAllStreamingConnections(); + if (failure instanceof StatusRuntimeException + && ((StatusRuntimeException) failure).getStatus().getCode() + == Status.Code.UNIMPLEMENTED) { + logger.info("Unable to open streaming connections, falling back to polling."); + startPollingConnections(); + return; + } + notifyFailed(failure); + } + }); } - private void startStreamingConnections() { - synchronized (streamingSubscriberConnections) { - for (int i = 0; i < numChannels; i++) { - streamingSubscriberConnections.add( - new StreamingSubscriberConnection( - cachedSubscriptionNameString, - credentials, - receiver, - ackExpirationPadding, - streamAckDeadlineSeconds, - ackLatencyDistribution, - channelBuilder.build(), - flowController, - executor, - clock)); - } - startConnections( - streamingSubscriberConnections, - new Listener() { + ackDeadlineUpdater = + executor.scheduleAtFixedRate( + new Runnable() { @Override - public void failed(State from, Throwable failure) { - // If a connection failed is because of a fatal error, we should fail the - // whole subscriber. - stopAllStreamingConnections(); - if (failure instanceof StatusRuntimeException - && ((StatusRuntimeException) failure).getStatus().getCode() - == Status.Code.UNIMPLEMENTED) { - logger.info("Unable to open streaming connections, falling back to polling."); - startPollingConnections(); - return; - } - notifyFailed(failure); - } - }); - } - - ackDeadlineUpdater = - executor.scheduleAtFixedRate( - new Runnable() { - @Override - public void run() { - // It is guaranteed this will be <= MAX_ACK_DEADLINE_SECONDS, the max of the API. - long ackLatency = - ackLatencyDistribution.getNthPercentile(PERCENTILE_FOR_ACK_DEADLINE_UPDATES); - if (ackLatency > 0) { - int possibleStreamAckDeadlineSeconds = - Math.max( - MIN_ACK_DEADLINE_SECONDS, - Ints.saturatedCast( - Math.max(ackLatency, ackExpirationPadding.getStandardSeconds()))); - if (streamAckDeadlineSeconds != possibleStreamAckDeadlineSeconds) { - streamAckDeadlineSeconds = possibleStreamAckDeadlineSeconds; - logger.log( - Level.FINER, - "Updating stream deadline to {0} seconds.", - streamAckDeadlineSeconds); - for (StreamingSubscriberConnection subscriberConnection : - streamingSubscriberConnections) { - subscriberConnection.updateStreamAckDeadline(streamAckDeadlineSeconds); - } + public void run() { + // It is guaranteed this will be <= MAX_ACK_DEADLINE_SECONDS, the max of the API. + long ackLatency = + ackLatencyDistribution.getNthPercentile(PERCENTILE_FOR_ACK_DEADLINE_UPDATES); + if (ackLatency > 0) { + int possibleStreamAckDeadlineSeconds = + Math.max( + MIN_ACK_DEADLINE_SECONDS, + Ints.saturatedCast( + Math.max(ackLatency, ackExpirationPadding.getStandardSeconds()))); + if (streamAckDeadlineSeconds != possibleStreamAckDeadlineSeconds) { + streamAckDeadlineSeconds = possibleStreamAckDeadlineSeconds; + logger.log( + Level.FINER, + "Updating stream deadline to {0} seconds.", + streamAckDeadlineSeconds); + for (StreamingSubscriberConnection subscriberConnection : + streamingSubscriberConnections) { + subscriberConnection.updateStreamAckDeadline(streamAckDeadlineSeconds); } } } - }, - ACK_DEADLINE_UPDATE_PERIOD.getMillis(), - ACK_DEADLINE_UPDATE_PERIOD.getMillis(), - TimeUnit.MILLISECONDS); - } + } + }, + ACK_DEADLINE_UPDATE_PERIOD.getMillis(), + ACK_DEADLINE_UPDATE_PERIOD.getMillis(), + TimeUnit.MILLISECONDS); + } - private void stopAllStreamingConnections() { - stopConnections(streamingSubscriberConnections); - if (ackDeadlineUpdater != null) { - ackDeadlineUpdater.cancel(true); - } + private void stopAllStreamingConnections() { + stopConnections(streamingSubscriberConnections); + if (ackDeadlineUpdater != null) { + ackDeadlineUpdater.cancel(true); } + } - private void startPollingConnections() { - synchronized (pollingSubscriberConnections) { - for (int i = 0; i < numChannels; i++) { - pollingSubscriberConnections.add( - new PollingSubscriberConnection( - cachedSubscriptionNameString, - credentials, - receiver, - ackExpirationPadding, - ackLatencyDistribution, - channelBuilder.build(), - flowController, - executor, - clock)); - } - startConnections( - pollingSubscriberConnections, - new Listener() { - @Override - public void failed(State from, Throwable failure) { - // If a connection failed is because of a fatal error, we should fail the - // whole subscriber. - stopAllPollingConnections(); - try { - notifyFailed(failure); - } catch (IllegalStateException e) { - if (isRunning()) { - throw e; - } - // It could happen that we are shutting down while some channels fail. + private void startPollingConnections() { + synchronized (pollingSubscriberConnections) { + for (int i = 0; i < numChannels; i++) { + pollingSubscriberConnections.add( + new PollingSubscriberConnection( + cachedSubscriptionNameString, + credentials, + receiver, + ackExpirationPadding, + ackLatencyDistribution, + channelBuilder.build(), + flowController, + executor, + clock)); + } + startConnections( + pollingSubscriberConnections, + new Listener() { + @Override + public void failed(State from, Throwable failure) { + // If a connection failed is because of a fatal error, we should fail the + // whole subscriber. + stopAllPollingConnections(); + try { + notifyFailed(failure); + } catch (IllegalStateException e) { + if (isRunning()) { + throw e; } + // It could happen that we are shutting down while some channels fail. } - }); - } + } + }); } + } - private void stopAllPollingConnections() { - stopConnections(pollingSubscriberConnections); - } + private void stopAllPollingConnections() { + stopConnections(pollingSubscriberConnections); + } - private void startConnections( - List connections, final Listener connectionsListener) { - final CountDownLatch subscribersStarting = new CountDownLatch(numChannels); - for (final Service subscriber : connections) { - executor.submit( - new Runnable() { - @Override - public void run() { - subscriber.addListener(connectionsListener, executor); - try { - subscriber.startAsync().awaitRunning(); - } finally { - subscribersStarting.countDown(); - } + private void startConnections( + List connections, final ApiService.Listener connectionsListener) { + final CountDownLatch subscribersStarting = new CountDownLatch(numChannels); + for (final ApiService subscriber : connections) { + executor.submit( + new Runnable() { + @Override + public void run() { + subscriber.addListener(connectionsListener, executor); + try { + subscriber.startAsync().awaitRunning(); + } finally { + subscribersStarting.countDown(); } - }); - } - try { - subscribersStarting.await(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } + } + }); } + try { + subscribersStarting.await(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } - private void stopConnections(List connections) { - ArrayList liveConnections; - synchronized (connections) { - liveConnections = new ArrayList(connections); - connections.clear(); - } - final CountDownLatch connectionsStopping = new CountDownLatch(liveConnections.size()); - for (final Service subscriberConnection : liveConnections) { - executor.submit( - new Runnable() { - @Override - public void run() { - try { - subscriberConnection.stopAsync().awaitTerminated(); - } catch (IllegalStateException ignored) { - // It is expected for some connections to be already in state failed so stop will - // throw this expection. - } - connectionsStopping.countDown(); + private void stopConnections(List connections) { + ArrayList liveConnections; + synchronized (connections) { + liveConnections = new ArrayList(connections); + connections.clear(); + } + final CountDownLatch connectionsStopping = new CountDownLatch(liveConnections.size()); + for (final ApiService subscriberConnection : liveConnections) { + executor.submit( + new Runnable() { + @Override + public void run() { + try { + subscriberConnection.stopAsync().awaitTerminated(); + } catch (IllegalStateException ignored) { + // It is expected for some connections to be already in state failed so stop will + // throw this expection. } - }); - } - try { - connectionsStopping.await(); - } catch (InterruptedException e) { - throw new IllegalStateException(e); - } + connectionsStopping.countDown(); + } + }); + } + try { + connectionsStopping.await(); + } catch (InterruptedException e) { + throw new IllegalStateException(e); } } diff --git a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/SubscriberClient.java b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/SubscriptionAdminClient.java similarity index 63% rename from google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/SubscriberClient.java rename to google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/SubscriptionAdminClient.java index 6f7f802fcbc6..531dfc99fa88 100644 --- a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/SubscriberClient.java +++ b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/SubscriptionAdminClient.java @@ -15,6 +15,7 @@ */ package com.google.cloud.pubsub.spi.v1; +import static com.google.cloud.pubsub.spi.v1.PagedResponseWrappers.ListSnapshotsPagedResponse; import static com.google.cloud.pubsub.spi.v1.PagedResponseWrappers.ListSubscriptionsPagedResponse; import com.google.api.gax.grpc.ChannelAndExecutor; @@ -28,8 +29,12 @@ import com.google.protobuf.Empty; import com.google.protobuf.ExperimentalApi; import com.google.pubsub.v1.AcknowledgeRequest; +import com.google.pubsub.v1.CreateSnapshotRequest; +import com.google.pubsub.v1.DeleteSnapshotRequest; import com.google.pubsub.v1.DeleteSubscriptionRequest; import com.google.pubsub.v1.GetSubscriptionRequest; +import com.google.pubsub.v1.ListSnapshotsRequest; +import com.google.pubsub.v1.ListSnapshotsResponse; import com.google.pubsub.v1.ListSubscriptionsRequest; import com.google.pubsub.v1.ListSubscriptionsResponse; import com.google.pubsub.v1.ModifyAckDeadlineRequest; @@ -38,12 +43,17 @@ import com.google.pubsub.v1.PullRequest; import com.google.pubsub.v1.PullResponse; import com.google.pubsub.v1.PushConfig; +import com.google.pubsub.v1.SeekRequest; +import com.google.pubsub.v1.SeekResponse; +import com.google.pubsub.v1.Snapshot; +import com.google.pubsub.v1.SnapshotName; import com.google.pubsub.v1.StreamingPullRequest; import com.google.pubsub.v1.StreamingPullResponse; import com.google.pubsub.v1.Subscription; import com.google.pubsub.v1.SubscriptionName; import com.google.pubsub.v1.TopicName; import com.google.pubsub.v1.TopicNameOneof; +import com.google.pubsub.v1.UpdateSubscriptionRequest; import io.grpc.ManagedChannel; import java.io.Closeable; import java.io.IOException; @@ -64,18 +74,19 @@ * *
      * 
    - * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    + * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
      *   SubscriptionName name = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
      *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
      *   PushConfig pushConfig = PushConfig.newBuilder().build();
      *   int ackDeadlineSeconds = 0;
    - *   Subscription response = subscriberClient.createSubscription(name, topic, pushConfig, ackDeadlineSeconds);
    + *   Subscription response = subscriptionAdminClient.createSubscription(name, topic, pushConfig, ackDeadlineSeconds);
      * }
      * 
      * 
    * - *

    Note: close() needs to be called on the subscriberClient object to clean up resources such as - * threads. In the example above, try-with-resources is used, which automatically calls close(). + *

    Note: close() needs to be called on the subscriptionAdminClient object to clean up resources + * such as threads. In the example above, try-with-resources is used, which automatically calls + * close(). * *

    The surface of this class includes several types of Java methods for each of the API's * methods: @@ -97,32 +108,33 @@ * these names, this class includes a format method for each type of name, and additionally a parse * method to extract the individual identifiers contained within names that are returned. * - *

    This class can be customized by passing in a custom instance of SubscriberSettings to + *

    This class can be customized by passing in a custom instance of SubscriptionAdminSettings to * create(). For example: * *

      * 
      * InstantiatingChannelProvider channelProvider =
    - *     SubscriberSettings.defaultChannelProviderBuilder()
    + *     SubscriptionAdminSettings.defaultChannelProviderBuilder()
      *         .setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
      *         .build();
    - * SubscriberSettings subscriberSettings =
    - *     SubscriberSettings.defaultBuilder().setChannelProvider(channelProvider).build();
    - * SubscriberClient subscriberClient =
    - *     SubscriberClient.create(subscriberSettings);
    + * SubscriptionAdminSettings subscriptionAdminSettings =
    + *     SubscriptionAdminSettings.defaultBuilder().setChannelProvider(channelProvider).build();
    + * SubscriptionAdminClient subscriptionAdminClient =
    + *     SubscriptionAdminClient.create(subscriptionAdminSettings);
      * 
      * 
    */ @Generated("by GAPIC") @ExperimentalApi -public class SubscriberClient implements AutoCloseable { - private final SubscriberSettings settings; +public class SubscriptionAdminClient implements AutoCloseable { + private final SubscriptionAdminSettings settings; private final ScheduledExecutorService executor; private final ManagedChannel channel; private final List closeables = new ArrayList<>(); private final UnaryCallable createSubscriptionCallable; private final UnaryCallable getSubscriptionCallable; + private final UnaryCallable updateSubscriptionCallable; private final UnaryCallable listSubscriptionsCallable; private final UnaryCallable @@ -134,29 +146,37 @@ public class SubscriberClient implements AutoCloseable { private final StreamingCallable streamingPullCallable; private final UnaryCallable modifyPushConfigCallable; + private final UnaryCallable listSnapshotsCallable; + private final UnaryCallable + listSnapshotsPagedCallable; + private final UnaryCallable createSnapshotCallable; + private final UnaryCallable deleteSnapshotCallable; + private final UnaryCallable seekCallable; private final UnaryCallable setIamPolicyCallable; private final UnaryCallable getIamPolicyCallable; private final UnaryCallable testIamPermissionsCallable; - /** Constructs an instance of SubscriberClient with default settings. */ - public static final SubscriberClient create() throws IOException { - return create(SubscriberSettings.defaultBuilder().build()); + /** Constructs an instance of SubscriptionAdminClient with default settings. */ + public static final SubscriptionAdminClient create() throws IOException { + return create(SubscriptionAdminSettings.defaultBuilder().build()); } /** - * Constructs an instance of SubscriberClient, using the given settings. The channels are created - * based on the settings passed in, or defaults for any settings that are not set. + * Constructs an instance of SubscriptionAdminClient, using the given settings. The channels are + * created based on the settings passed in, or defaults for any settings that are not set. */ - public static final SubscriberClient create(SubscriberSettings settings) throws IOException { - return new SubscriberClient(settings); + public static final SubscriptionAdminClient create(SubscriptionAdminSettings settings) + throws IOException { + return new SubscriptionAdminClient(settings); } /** - * Constructs an instance of SubscriberClient, using the given settings. This is protected so that - * it easy to make a subclass, but otherwise, the static factory methods should be preferred. + * Constructs an instance of SubscriptionAdminClient, using the given settings. This is protected + * so that it easy to make a subclass, but otherwise, the static factory methods should be + * preferred. */ - protected SubscriberClient(SubscriberSettings settings) throws IOException { + protected SubscriptionAdminClient(SubscriptionAdminSettings settings) throws IOException { this.settings = settings; ChannelAndExecutor channelAndExecutor = settings.getChannelAndExecutor(); this.executor = channelAndExecutor.getExecutor(); @@ -166,6 +186,8 @@ protected SubscriberClient(SubscriberSettings settings) throws IOException { UnaryCallable.create(settings.createSubscriptionSettings(), this.channel, this.executor); this.getSubscriptionCallable = UnaryCallable.create(settings.getSubscriptionSettings(), this.channel, this.executor); + this.updateSubscriptionCallable = + UnaryCallable.create(settings.updateSubscriptionSettings(), this.channel, this.executor); this.listSubscriptionsCallable = UnaryCallable.create(settings.listSubscriptionsSettings(), this.channel, this.executor); this.listSubscriptionsPagedCallable = @@ -182,6 +204,16 @@ protected SubscriberClient(SubscriberSettings settings) throws IOException { StreamingCallable.create(settings.streamingPullSettings(), this.channel); this.modifyPushConfigCallable = UnaryCallable.create(settings.modifyPushConfigSettings(), this.channel, this.executor); + this.listSnapshotsCallable = + UnaryCallable.create(settings.listSnapshotsSettings(), this.channel, this.executor); + this.listSnapshotsPagedCallable = + UnaryCallable.createPagedVariant( + settings.listSnapshotsSettings(), this.channel, this.executor); + this.createSnapshotCallable = + UnaryCallable.create(settings.createSnapshotSettings(), this.channel, this.executor); + this.deleteSnapshotCallable = + UnaryCallable.create(settings.deleteSnapshotSettings(), this.channel, this.executor); + this.seekCallable = UnaryCallable.create(settings.seekSettings(), this.channel, this.executor); this.setIamPolicyCallable = UnaryCallable.create(settings.setIamPolicySettings(), this.channel, this.executor); this.getIamPolicyCallable = @@ -209,7 +241,7 @@ public void close() throws IOException { } } - public final SubscriberSettings getSettings() { + public final SubscriptionAdminSettings getSettings() { return settings; } @@ -227,12 +259,12 @@ public final SubscriberSettings getSettings() { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName name = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
        *   PushConfig pushConfig = PushConfig.newBuilder().build();
        *   int ackDeadlineSeconds = 0;
    -   *   Subscription response = subscriberClient.createSubscription(name, topic, pushConfig, ackDeadlineSeconds);
    +   *   Subscription response = subscriptionAdminClient.createSubscription(name, topic, pushConfig, ackDeadlineSeconds);
        * }
        * 
    * @@ -289,14 +321,14 @@ public final Subscription createSubscription( *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName name = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   TopicNameOneof topic = TopicNameOneof.from(TopicName.create("[PROJECT]", "[TOPIC]"));
        *   Subscription request = Subscription.newBuilder()
        *     .setNameWithSubscriptionName(name)
        *     .setTopicWithTopicName(topic)
        *     .build();
    -   *   Subscription response = subscriberClient.createSubscription(request);
    +   *   Subscription response = subscriptionAdminClient.createSubscription(request);
        * }
        * 
    * @@ -321,14 +353,14 @@ public final Subscription createSubscription(Subscription request) { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName name = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   TopicNameOneof topic = TopicNameOneof.from(TopicName.create("[PROJECT]", "[TOPIC]"));
        *   Subscription request = Subscription.newBuilder()
        *     .setNameWithSubscriptionName(name)
        *     .setTopicWithTopicName(topic)
        *     .build();
    -   *   ApiFuture<Subscription> future = subscriberClient.createSubscriptionCallable().futureCall(request);
    +   *   ApiFuture<Subscription> future = subscriptionAdminClient.createSubscriptionCallable().futureCall(request);
        *   // Do something
        *   Subscription response = future.get();
        * }
    @@ -345,9 +377,9 @@ public final UnaryCallable createSubscriptionCallabl
        * 

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
    -   *   Subscription response = subscriberClient.getSubscription(subscription);
    +   *   Subscription response = subscriptionAdminClient.getSubscription(subscription);
        * }
        * 
    * @@ -371,12 +403,12 @@ public final Subscription getSubscription(SubscriptionName subscription) { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   GetSubscriptionRequest request = GetSubscriptionRequest.newBuilder()
        *     .setSubscriptionWithSubscriptionName(subscription)
        *     .build();
    -   *   Subscription response = subscriberClient.getSubscription(request);
    +   *   Subscription response = subscriptionAdminClient.getSubscription(request);
        * }
        * 
    * @@ -394,12 +426,12 @@ private final Subscription getSubscription(GetSubscriptionRequest request) { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   GetSubscriptionRequest request = GetSubscriptionRequest.newBuilder()
        *     .setSubscriptionWithSubscriptionName(subscription)
        *     .build();
    -   *   ApiFuture<Subscription> future = subscriberClient.getSubscriptionCallable().futureCall(request);
    +   *   ApiFuture<Subscription> future = subscriptionAdminClient.getSubscriptionCallable().futureCall(request);
        *   // Do something
        *   Subscription response = future.get();
        * }
    @@ -409,6 +441,58 @@ public final UnaryCallable getSubscription
         return getSubscriptionCallable;
       }
     
    +  // AUTO-GENERATED DOCUMENTATION AND METHOD
    +  /**
    +   * Updates an existing subscription. Note that certain properties of a subscription, such as its
    +   * topic, are not modifiable.
    +   *
    +   * 

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   Subscription subscription = Subscription.newBuilder().build();
    +   *   FieldMask updateMask = FieldMask.newBuilder().build();
    +   *   UpdateSubscriptionRequest request = UpdateSubscriptionRequest.newBuilder()
    +   *     .setSubscription(subscription)
    +   *     .setUpdateMask(updateMask)
    +   *     .build();
    +   *   Subscription response = subscriptionAdminClient.updateSubscription(request);
    +   * }
    +   * 
    + * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + /* package-private */ final Subscription updateSubscription(UpdateSubscriptionRequest request) { + return updateSubscriptionCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Updates an existing subscription. Note that certain properties of a subscription, such as its + * topic, are not modifiable. + * + *

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   Subscription subscription = Subscription.newBuilder().build();
    +   *   FieldMask updateMask = FieldMask.newBuilder().build();
    +   *   UpdateSubscriptionRequest request = UpdateSubscriptionRequest.newBuilder()
    +   *     .setSubscription(subscription)
    +   *     .setUpdateMask(updateMask)
    +   *     .build();
    +   *   ApiFuture<Subscription> future = subscriptionAdminClient.updateSubscriptionCallable().futureCall(request);
    +   *   // Do something
    +   *   Subscription response = future.get();
    +   * }
    +   * 
    + */ + /* package-private */ final UnaryCallable + updateSubscriptionCallable() { + return updateSubscriptionCallable; + } + // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Lists matching subscriptions. @@ -416,9 +500,9 @@ public final UnaryCallable getSubscription *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   ProjectName project = ProjectName.create("[PROJECT]");
    -   *   for (Subscription element : subscriberClient.listSubscriptions(project).iterateAllElements()) {
    +   *   for (Subscription element : subscriptionAdminClient.listSubscriptions(project).iterateAllElements()) {
        *     // doThingsWith(element);
        *   }
        * }
    @@ -441,12 +525,12 @@ public final ListSubscriptionsPagedResponse listSubscriptions(ProjectName projec
        * 

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   ProjectName project = ProjectName.create("[PROJECT]");
        *   ListSubscriptionsRequest request = ListSubscriptionsRequest.newBuilder()
        *     .setProjectWithProjectName(project)
        *     .build();
    -   *   for (Subscription element : subscriberClient.listSubscriptions(request).iterateAllElements()) {
    +   *   for (Subscription element : subscriptionAdminClient.listSubscriptions(request).iterateAllElements()) {
        *     // doThingsWith(element);
        *   }
        * }
    @@ -466,12 +550,12 @@ public final ListSubscriptionsPagedResponse listSubscriptions(ListSubscriptionsR
        * 

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   ProjectName project = ProjectName.create("[PROJECT]");
        *   ListSubscriptionsRequest request = ListSubscriptionsRequest.newBuilder()
        *     .setProjectWithProjectName(project)
        *     .build();
    -   *   ApiFuture<ListSubscriptionsPagedResponse> future = subscriberClient.listSubscriptionsPagedCallable().futureCall(request);
    +   *   ApiFuture<ListSubscriptionsPagedResponse> future = subscriptionAdminClient.listSubscriptionsPagedCallable().futureCall(request);
        *   // Do something
        *   for (Subscription element : future.get().iterateAllElements()) {
        *     // doThingsWith(element);
    @@ -491,13 +575,13 @@ public final ListSubscriptionsPagedResponse listSubscriptions(ListSubscriptionsR
        * 

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   ProjectName project = ProjectName.create("[PROJECT]");
        *   ListSubscriptionsRequest request = ListSubscriptionsRequest.newBuilder()
        *     .setProjectWithProjectName(project)
        *     .build();
        *   while (true) {
    -   *     ListSubscriptionsResponse response = subscriberClient.listSubscriptionsCallable().call(request);
    +   *     ListSubscriptionsResponse response = subscriptionAdminClient.listSubscriptionsCallable().call(request);
        *     for (Subscription element : response.getSubscriptionsList()) {
        *       // doThingsWith(element);
        *     }
    @@ -526,9 +610,9 @@ public final ListSubscriptionsPagedResponse listSubscriptions(ListSubscriptionsR
        * 

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
    -   *   subscriberClient.deleteSubscription(subscription);
    +   *   subscriptionAdminClient.deleteSubscription(subscription);
        * }
        * 
    * @@ -555,12 +639,12 @@ public final void deleteSubscription(SubscriptionName subscription) { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   DeleteSubscriptionRequest request = DeleteSubscriptionRequest.newBuilder()
        *     .setSubscriptionWithSubscriptionName(subscription)
        *     .build();
    -   *   subscriberClient.deleteSubscription(request);
    +   *   subscriptionAdminClient.deleteSubscription(request);
        * }
        * 
    * @@ -581,12 +665,12 @@ private final void deleteSubscription(DeleteSubscriptionRequest request) { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   DeleteSubscriptionRequest request = DeleteSubscriptionRequest.newBuilder()
        *     .setSubscriptionWithSubscriptionName(subscription)
        *     .build();
    -   *   ApiFuture<Void> future = subscriberClient.deleteSubscriptionCallable().futureCall(request);
    +   *   ApiFuture<Void> future = subscriptionAdminClient.deleteSubscriptionCallable().futureCall(request);
        *   // Do something
        *   future.get();
        * }
    @@ -606,11 +690,11 @@ public final UnaryCallable deleteSubscriptionC
        * 

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   List<String> ackIds = new ArrayList<>();
        *   int ackDeadlineSeconds = 0;
    -   *   subscriberClient.modifyAckDeadline(subscription, ackIds, ackDeadlineSeconds);
    +   *   subscriptionAdminClient.modifyAckDeadline(subscription, ackIds, ackDeadlineSeconds);
        * }
        * 
    * @@ -624,7 +708,7 @@ public final UnaryCallable deleteSubscriptionC * seconds. The maximum deadline you can specify is 600 seconds (10 minutes). * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public final void modifyAckDeadline( + /* package-private */ final void modifyAckDeadline( SubscriptionName subscription, List ackIds, int ackDeadlineSeconds) { ModifyAckDeadlineRequest request = @@ -646,7 +730,7 @@ public final void modifyAckDeadline( *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   List<String> ackIds = new ArrayList<>();
        *   int ackDeadlineSeconds = 0;
    @@ -655,14 +739,14 @@ public final void modifyAckDeadline(
        *     .addAllAckIds(ackIds)
        *     .setAckDeadlineSeconds(ackDeadlineSeconds)
        *     .build();
    -   *   subscriberClient.modifyAckDeadline(request);
    +   *   subscriptionAdminClient.modifyAckDeadline(request);
        * }
        * 
    * * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public final void modifyAckDeadline(ModifyAckDeadlineRequest request) { + /* package-private */ final void modifyAckDeadline(ModifyAckDeadlineRequest request) { modifyAckDeadlineCallable().call(request); } @@ -676,7 +760,7 @@ public final void modifyAckDeadline(ModifyAckDeadlineRequest request) { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   List<String> ackIds = new ArrayList<>();
        *   int ackDeadlineSeconds = 0;
    @@ -685,13 +769,14 @@ public final void modifyAckDeadline(ModifyAckDeadlineRequest request) {
        *     .addAllAckIds(ackIds)
        *     .setAckDeadlineSeconds(ackDeadlineSeconds)
        *     .build();
    -   *   ApiFuture<Void> future = subscriberClient.modifyAckDeadlineCallable().futureCall(request);
    +   *   ApiFuture<Void> future = subscriptionAdminClient.modifyAckDeadlineCallable().futureCall(request);
        *   // Do something
        *   future.get();
        * }
        * 
    */ - public final UnaryCallable modifyAckDeadlineCallable() { + /* package-private */ final UnaryCallable + modifyAckDeadlineCallable() { return modifyAckDeadlineCallable; } @@ -706,10 +791,10 @@ public final UnaryCallable modifyAckDeadlineCal *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   List<String> ackIds = new ArrayList<>();
    -   *   subscriberClient.acknowledge(subscription, ackIds);
    +   *   subscriptionAdminClient.acknowledge(subscription, ackIds);
        * }
        * 
    * @@ -719,7 +804,7 @@ public final UnaryCallable modifyAckDeadlineCal * the Pub/Sub system in the `Pull` response. Must not be empty. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public final void acknowledge(SubscriptionName subscription, List ackIds) { + /* package-private */ final void acknowledge(SubscriptionName subscription, List ackIds) { AcknowledgeRequest request = AcknowledgeRequest.newBuilder() @@ -740,21 +825,21 @@ public final void acknowledge(SubscriptionName subscription, List ackIds *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   List<String> ackIds = new ArrayList<>();
        *   AcknowledgeRequest request = AcknowledgeRequest.newBuilder()
        *     .setSubscriptionWithSubscriptionName(subscription)
        *     .addAllAckIds(ackIds)
        *     .build();
    -   *   subscriberClient.acknowledge(request);
    +   *   subscriptionAdminClient.acknowledge(request);
        * }
        * 
    * * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public final void acknowledge(AcknowledgeRequest request) { + /* package-private */ final void acknowledge(AcknowledgeRequest request) { acknowledgeCallable().call(request); } @@ -769,20 +854,20 @@ public final void acknowledge(AcknowledgeRequest request) { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   List<String> ackIds = new ArrayList<>();
        *   AcknowledgeRequest request = AcknowledgeRequest.newBuilder()
        *     .setSubscriptionWithSubscriptionName(subscription)
        *     .addAllAckIds(ackIds)
        *     .build();
    -   *   ApiFuture<Void> future = subscriberClient.acknowledgeCallable().futureCall(request);
    +   *   ApiFuture<Void> future = subscriptionAdminClient.acknowledgeCallable().futureCall(request);
        *   // Do something
        *   future.get();
        * }
        * 
    */ - public final UnaryCallable acknowledgeCallable() { + /* package-private */ final UnaryCallable acknowledgeCallable() { return acknowledgeCallable; } @@ -795,11 +880,11 @@ public final UnaryCallable acknowledgeCallable() { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   boolean returnImmediately = false;
        *   int maxMessages = 0;
    -   *   PullResponse response = subscriberClient.pull(subscription, returnImmediately, maxMessages);
    +   *   PullResponse response = subscriptionAdminClient.pull(subscription, returnImmediately, maxMessages);
        * }
        * 
    * @@ -814,7 +899,7 @@ public final UnaryCallable acknowledgeCallable() { * may return fewer than the number specified. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public final PullResponse pull( + /* package-private */ final PullResponse pull( SubscriptionName subscription, boolean returnImmediately, int maxMessages) { PullRequest request = @@ -835,21 +920,21 @@ public final PullResponse pull( *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   int maxMessages = 0;
        *   PullRequest request = PullRequest.newBuilder()
        *     .setSubscriptionWithSubscriptionName(subscription)
        *     .setMaxMessages(maxMessages)
        *     .build();
    -   *   PullResponse response = subscriberClient.pull(request);
    +   *   PullResponse response = subscriptionAdminClient.pull(request);
        * }
        * 
    * * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public final PullResponse pull(PullRequest request) { + /* package-private */ final PullResponse pull(PullRequest request) { return pullCallable().call(request); } @@ -862,20 +947,20 @@ public final PullResponse pull(PullRequest request) { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   int maxMessages = 0;
        *   PullRequest request = PullRequest.newBuilder()
        *     .setSubscriptionWithSubscriptionName(subscription)
        *     .setMaxMessages(maxMessages)
        *     .build();
    -   *   ApiFuture<PullResponse> future = subscriberClient.pullCallable().futureCall(request);
    +   *   ApiFuture<PullResponse> future = subscriptionAdminClient.pullCallable().futureCall(request);
        *   // Do something
        *   PullResponse response = future.get();
        * }
        * 
    */ - public final UnaryCallable pullCallable() { + /* package-private */ final UnaryCallable pullCallable() { return pullCallable; } @@ -896,7 +981,7 @@ public final UnaryCallable pullCallable() { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   ApiStreamObserver<StreamingPullResponse> responseObserver =
        *       new ApiStreamObserver<StreamingPullResponse>() {
        *         {@literal @}Override
    @@ -915,7 +1000,7 @@ public final UnaryCallable pullCallable() {
        *         }
        *       };
        *   ApiStreamObserver<StreamingRecognizeRequest> requestObserver =
    -   *       subscriberClient.streamingPullCallable().bidiStreamingCall(responseObserver)});
    +   *       subscriptionAdminClient.streamingPullCallable().bidiStreamingCall(responseObserver)});
        *
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   int streamAckDeadlineSeconds = 0;
    @@ -944,10 +1029,10 @@ public final UnaryCallable pullCallable() {
        * 

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   PushConfig pushConfig = PushConfig.newBuilder().build();
    -   *   subscriberClient.modifyPushConfig(subscription, pushConfig);
    +   *   subscriptionAdminClient.modifyPushConfig(subscription, pushConfig);
        * }
        * 
    * @@ -981,14 +1066,14 @@ public final void modifyPushConfig(SubscriptionName subscription, PushConfig pus *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   PushConfig pushConfig = PushConfig.newBuilder().build();
        *   ModifyPushConfigRequest request = ModifyPushConfigRequest.newBuilder()
        *     .setSubscriptionWithSubscriptionName(subscription)
        *     .setPushConfig(pushConfig)
        *     .build();
    -   *   subscriberClient.modifyPushConfig(request);
    +   *   subscriptionAdminClient.modifyPushConfig(request);
        * }
        * 
    * @@ -1011,14 +1096,14 @@ public final void modifyPushConfig(ModifyPushConfigRequest request) { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
        *   PushConfig pushConfig = PushConfig.newBuilder().build();
        *   ModifyPushConfigRequest request = ModifyPushConfigRequest.newBuilder()
        *     .setSubscriptionWithSubscriptionName(subscription)
        *     .setPushConfig(pushConfig)
        *     .build();
    -   *   ApiFuture<Void> future = subscriberClient.modifyPushConfigCallable().futureCall(request);
    +   *   ApiFuture<Void> future = subscriptionAdminClient.modifyPushConfigCallable().futureCall(request);
        *   // Do something
        *   future.get();
        * }
    @@ -1028,6 +1113,343 @@ public final UnaryCallable modifyPushConfigCalla
         return modifyPushConfigCallable;
       }
     
    +  // AUTO-GENERATED DOCUMENTATION AND METHOD
    +  /**
    +   * Lists the existing snapshots.
    +   *
    +   * 

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   ProjectName project = ProjectName.create("[PROJECT]");
    +   *   for (Snapshot element : subscriptionAdminClient.listSnapshots(project).iterateAllElements()) {
    +   *     // doThingsWith(element);
    +   *   }
    +   * }
    +   * 
    + * + * @param project The name of the cloud project that snapshots belong to. Format is + * `projects/{project}`. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final ListSnapshotsPagedResponse listSnapshots(ProjectName project) { + ListSnapshotsRequest request = + ListSnapshotsRequest.newBuilder().setProjectWithProjectName(project).build(); + return listSnapshots(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists the existing snapshots. + * + *

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   ProjectName project = ProjectName.create("[PROJECT]");
    +   *   ListSnapshotsRequest request = ListSnapshotsRequest.newBuilder()
    +   *     .setProjectWithProjectName(project)
    +   *     .build();
    +   *   for (Snapshot element : subscriptionAdminClient.listSnapshots(request).iterateAllElements()) {
    +   *     // doThingsWith(element);
    +   *   }
    +   * }
    +   * 
    + * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final ListSnapshotsPagedResponse listSnapshots(ListSnapshotsRequest request) { + return listSnapshotsPagedCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists the existing snapshots. + * + *

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   ProjectName project = ProjectName.create("[PROJECT]");
    +   *   ListSnapshotsRequest request = ListSnapshotsRequest.newBuilder()
    +   *     .setProjectWithProjectName(project)
    +   *     .build();
    +   *   ApiFuture<ListSnapshotsPagedResponse> future = subscriptionAdminClient.listSnapshotsPagedCallable().futureCall(request);
    +   *   // Do something
    +   *   for (Snapshot element : future.get().iterateAllElements()) {
    +   *     // doThingsWith(element);
    +   *   }
    +   * }
    +   * 
    + */ + public final UnaryCallable + listSnapshotsPagedCallable() { + return listSnapshotsPagedCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists the existing snapshots. + * + *

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   ProjectName project = ProjectName.create("[PROJECT]");
    +   *   ListSnapshotsRequest request = ListSnapshotsRequest.newBuilder()
    +   *     .setProjectWithProjectName(project)
    +   *     .build();
    +   *   while (true) {
    +   *     ListSnapshotsResponse response = subscriptionAdminClient.listSnapshotsCallable().call(request);
    +   *     for (Snapshot element : response.getSnapshotsList()) {
    +   *       // doThingsWith(element);
    +   *     }
    +   *     String nextPageToken = response.getNextPageToken();
    +   *     if (!Strings.isNullOrEmpty(nextPageToken)) {
    +   *       request = request.toBuilder().setPageToken(nextPageToken).build();
    +   *     } else {
    +   *       break;
    +   *     }
    +   *   }
    +   * }
    +   * 
    + */ + public final UnaryCallable listSnapshotsCallable() { + return listSnapshotsCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Creates a snapshot from the requested subscription. If the snapshot already exists, returns + * `ALREADY_EXISTS`. If the requested subscription doesn't exist, returns `NOT_FOUND`. + * + *

    If the name is not provided in the request, the server will assign a random name for this + * snapshot on the same project as the subscription, conforming to the [resource name + * format](https://cloud.google.com/pubsub/docs/overview#names). The generated name is populated + * in the returned Snapshot object. Note that for REST API requests, you must specify a name in + * the request. + * + *

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   SnapshotName name = SnapshotName.create("[PROJECT]", "[SNAPSHOT]");
    +   *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
    +   *   Snapshot response = subscriptionAdminClient.createSnapshot(name, subscription);
    +   * }
    +   * 
    + * + * @param name Optional user-provided name for this snapshot. If the name is not provided in the + * request, the server will assign a random name for this snapshot on the same project as the + * subscription. Note that for REST API requests, you must specify a name. Format is + * `projects/{project}/snapshots/{snap}`. + * @param subscription The subscription whose backlog the snapshot retains. Specifically, the + * created snapshot is guaranteed to retain: (a) The existing backlog on the subscription. + * More precisely, this is defined as the messages in the subscription's backlog that are + * unacknowledged upon the successful completion of the `CreateSnapshot` request; as well as: + * (b) Any messages published to the subscription's topic following the successful completion + * of the CreateSnapshot request. Format is `projects/{project}/subscriptions/{sub}`. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Snapshot createSnapshot(SnapshotName name, SubscriptionName subscription) { + + CreateSnapshotRequest request = + CreateSnapshotRequest.newBuilder() + .setNameWithSnapshotName(name) + .setSubscriptionWithSubscriptionName(subscription) + .build(); + return createSnapshot(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Creates a snapshot from the requested subscription. If the snapshot already exists, returns + * `ALREADY_EXISTS`. If the requested subscription doesn't exist, returns `NOT_FOUND`. + * + *

    If the name is not provided in the request, the server will assign a random name for this + * snapshot on the same project as the subscription, conforming to the [resource name + * format](https://cloud.google.com/pubsub/docs/overview#names). The generated name is populated + * in the returned Snapshot object. Note that for REST API requests, you must specify a name in + * the request. + * + *

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   SnapshotName name = SnapshotName.create("[PROJECT]", "[SNAPSHOT]");
    +   *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
    +   *   CreateSnapshotRequest request = CreateSnapshotRequest.newBuilder()
    +   *     .setNameWithSnapshotName(name)
    +   *     .setSubscriptionWithSubscriptionName(subscription)
    +   *     .build();
    +   *   Snapshot response = subscriptionAdminClient.createSnapshot(request);
    +   * }
    +   * 
    + * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Snapshot createSnapshot(CreateSnapshotRequest request) { + return createSnapshotCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Creates a snapshot from the requested subscription. If the snapshot already exists, returns + * `ALREADY_EXISTS`. If the requested subscription doesn't exist, returns `NOT_FOUND`. + * + *

    If the name is not provided in the request, the server will assign a random name for this + * snapshot on the same project as the subscription, conforming to the [resource name + * format](https://cloud.google.com/pubsub/docs/overview#names). The generated name is populated + * in the returned Snapshot object. Note that for REST API requests, you must specify a name in + * the request. + * + *

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   SnapshotName name = SnapshotName.create("[PROJECT]", "[SNAPSHOT]");
    +   *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
    +   *   CreateSnapshotRequest request = CreateSnapshotRequest.newBuilder()
    +   *     .setNameWithSnapshotName(name)
    +   *     .setSubscriptionWithSubscriptionName(subscription)
    +   *     .build();
    +   *   ApiFuture<Snapshot> future = subscriptionAdminClient.createSnapshotCallable().futureCall(request);
    +   *   // Do something
    +   *   Snapshot response = future.get();
    +   * }
    +   * 
    + */ + public final UnaryCallable createSnapshotCallable() { + return createSnapshotCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Removes an existing snapshot. All messages retained in the snapshot are immediately dropped. + * After a snapshot is deleted, a new one may be created with the same name, but the new one has + * no association with the old snapshot or its subscription, unless the same subscription is + * specified. + * + *

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   SnapshotName snapshot = SnapshotName.create("[PROJECT]", "[SNAPSHOT]");
    +   *   subscriptionAdminClient.deleteSnapshot(snapshot);
    +   * }
    +   * 
    + * + * @param snapshot The name of the snapshot to delete. Format is + * `projects/{project}/snapshots/{snap}`. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final void deleteSnapshot(SnapshotName snapshot) { + + DeleteSnapshotRequest request = + DeleteSnapshotRequest.newBuilder().setSnapshotWithSnapshotName(snapshot).build(); + deleteSnapshot(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Removes an existing snapshot. All messages retained in the snapshot are immediately dropped. + * After a snapshot is deleted, a new one may be created with the same name, but the new one has + * no association with the old snapshot or its subscription, unless the same subscription is + * specified. + * + *

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   SnapshotName snapshot = SnapshotName.create("[PROJECT]", "[SNAPSHOT]");
    +   *   DeleteSnapshotRequest request = DeleteSnapshotRequest.newBuilder()
    +   *     .setSnapshotWithSnapshotName(snapshot)
    +   *     .build();
    +   *   subscriptionAdminClient.deleteSnapshot(request);
    +   * }
    +   * 
    + * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + private final void deleteSnapshot(DeleteSnapshotRequest request) { + deleteSnapshotCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Removes an existing snapshot. All messages retained in the snapshot are immediately dropped. + * After a snapshot is deleted, a new one may be created with the same name, but the new one has + * no association with the old snapshot or its subscription, unless the same subscription is + * specified. + * + *

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   SnapshotName snapshot = SnapshotName.create("[PROJECT]", "[SNAPSHOT]");
    +   *   DeleteSnapshotRequest request = DeleteSnapshotRequest.newBuilder()
    +   *     .setSnapshotWithSnapshotName(snapshot)
    +   *     .build();
    +   *   ApiFuture<Void> future = subscriptionAdminClient.deleteSnapshotCallable().futureCall(request);
    +   *   // Do something
    +   *   future.get();
    +   * }
    +   * 
    + */ + public final UnaryCallable deleteSnapshotCallable() { + return deleteSnapshotCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Seeks an existing subscription to a point in time or to a given snapshot, whichever is provided + * in the request. + * + *

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
    +   *   SeekRequest request = SeekRequest.newBuilder()
    +   *     .setSubscriptionWithSubscriptionName(subscription)
    +   *     .build();
    +   *   SeekResponse response = subscriptionAdminClient.seek(request);
    +   * }
    +   * 
    + * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final SeekResponse seek(SeekRequest request) { + return seekCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Seeks an existing subscription to a point in time or to a given snapshot, whichever is provided + * in the request. + * + *

    Sample code: + * + *

    
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    +   *   SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
    +   *   SeekRequest request = SeekRequest.newBuilder()
    +   *     .setSubscriptionWithSubscriptionName(subscription)
    +   *     .build();
    +   *   ApiFuture<SeekResponse> future = subscriptionAdminClient.seekCallable().futureCall(request);
    +   *   // Do something
    +   *   SeekResponse response = future.get();
    +   * }
    +   * 
    + */ + public final UnaryCallable seekCallable() { + return seekCallable; + } + // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Sets the access control policy on the specified resource. Replaces any existing policy. @@ -1035,10 +1457,10 @@ public final UnaryCallable modifyPushConfigCalla *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   String formattedResource = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]").toString();
        *   Policy policy = Policy.newBuilder().build();
    -   *   Policy response = subscriberClient.setIamPolicy(formattedResource, policy);
    +   *   Policy response = subscriptionAdminClient.setIamPolicy(formattedResource, policy);
        * }
        * 
    * @@ -1064,14 +1486,14 @@ public final Policy setIamPolicy(String resource, Policy policy) { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   String formattedResource = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]").toString();
        *   Policy policy = Policy.newBuilder().build();
        *   SetIamPolicyRequest request = SetIamPolicyRequest.newBuilder()
        *     .setResource(formattedResource)
        *     .setPolicy(policy)
        *     .build();
    -   *   Policy response = subscriberClient.setIamPolicy(request);
    +   *   Policy response = subscriptionAdminClient.setIamPolicy(request);
        * }
        * 
    * @@ -1089,14 +1511,14 @@ public final Policy setIamPolicy(SetIamPolicyRequest request) { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   String formattedResource = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]").toString();
        *   Policy policy = Policy.newBuilder().build();
        *   SetIamPolicyRequest request = SetIamPolicyRequest.newBuilder()
        *     .setResource(formattedResource)
        *     .setPolicy(policy)
        *     .build();
    -   *   ApiFuture<Policy> future = subscriberClient.setIamPolicyCallable().futureCall(request);
    +   *   ApiFuture<Policy> future = subscriptionAdminClient.setIamPolicyCallable().futureCall(request);
        *   // Do something
        *   Policy response = future.get();
        * }
    @@ -1114,9 +1536,9 @@ public final UnaryCallable setIamPolicyCallable() {
        * 

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   String formattedResource = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]").toString();
    -   *   Policy response = subscriberClient.getIamPolicy(formattedResource);
    +   *   Policy response = subscriptionAdminClient.getIamPolicy(formattedResource);
        * }
        * 
    * @@ -1139,12 +1561,12 @@ public final Policy getIamPolicy(String resource) { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   String formattedResource = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]").toString();
        *   GetIamPolicyRequest request = GetIamPolicyRequest.newBuilder()
        *     .setResource(formattedResource)
        *     .build();
    -   *   Policy response = subscriberClient.getIamPolicy(request);
    +   *   Policy response = subscriptionAdminClient.getIamPolicy(request);
        * }
        * 
    * @@ -1163,12 +1585,12 @@ private final Policy getIamPolicy(GetIamPolicyRequest request) { *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   String formattedResource = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]").toString();
        *   GetIamPolicyRequest request = GetIamPolicyRequest.newBuilder()
        *     .setResource(formattedResource)
        *     .build();
    -   *   ApiFuture<Policy> future = subscriberClient.getIamPolicyCallable().futureCall(request);
    +   *   ApiFuture<Policy> future = subscriptionAdminClient.getIamPolicyCallable().futureCall(request);
        *   // Do something
        *   Policy response = future.get();
        * }
    @@ -1186,10 +1608,10 @@ public final UnaryCallable getIamPolicyCallable() {
        * 

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   String formattedResource = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]").toString();
        *   List<String> permissions = new ArrayList<>();
    -   *   TestIamPermissionsResponse response = subscriberClient.testIamPermissions(formattedResource, permissions);
    +   *   TestIamPermissionsResponse response = subscriptionAdminClient.testIamPermissions(formattedResource, permissions);
        * }
        * 
    * @@ -1220,14 +1642,14 @@ public final TestIamPermissionsResponse testIamPermissions( *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   String formattedResource = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]").toString();
        *   List<String> permissions = new ArrayList<>();
        *   TestIamPermissionsRequest request = TestIamPermissionsRequest.newBuilder()
        *     .setResource(formattedResource)
        *     .addAllPermissions(permissions)
        *     .build();
    -   *   TestIamPermissionsResponse response = subscriberClient.testIamPermissions(request);
    +   *   TestIamPermissionsResponse response = subscriptionAdminClient.testIamPermissions(request);
        * }
        * 
    * @@ -1246,14 +1668,14 @@ public final TestIamPermissionsResponse testIamPermissions(TestIamPermissionsReq *

    Sample code: * *

    
    -   * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    +   * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
        *   String formattedResource = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]").toString();
        *   List<String> permissions = new ArrayList<>();
        *   TestIamPermissionsRequest request = TestIamPermissionsRequest.newBuilder()
        *     .setResource(formattedResource)
        *     .addAllPermissions(permissions)
        *     .build();
    -   *   ApiFuture<TestIamPermissionsResponse> future = subscriberClient.testIamPermissionsCallable().futureCall(request);
    +   *   ApiFuture<TestIamPermissionsResponse> future = subscriptionAdminClient.testIamPermissionsCallable().futureCall(request);
        *   // Do something
        *   TestIamPermissionsResponse response = future.get();
        * }
    diff --git a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/SubscriberSettings.java b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/SubscriptionAdminSettings.java
    similarity index 71%
    rename from google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/SubscriberSettings.java
    rename to google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/SubscriptionAdminSettings.java
    index bca03b5eb593..f28ca0cb58ef 100644
    --- a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/SubscriberSettings.java
    +++ b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/SubscriptionAdminSettings.java
    @@ -15,9 +15,11 @@
      */
     package com.google.cloud.pubsub.spi.v1;
     
    +import static com.google.cloud.pubsub.spi.v1.PagedResponseWrappers.ListSnapshotsPagedResponse;
     import static com.google.cloud.pubsub.spi.v1.PagedResponseWrappers.ListSubscriptionsPagedResponse;
     
     import com.google.api.gax.core.GoogleCredentialsProvider;
    +import com.google.api.gax.core.PropertiesProvider;
     import com.google.api.gax.core.RetrySettings;
     import com.google.api.gax.grpc.CallContext;
     import com.google.api.gax.grpc.ChannelProvider;
    @@ -46,18 +48,26 @@
     import com.google.protobuf.Empty;
     import com.google.protobuf.ExperimentalApi;
     import com.google.pubsub.v1.AcknowledgeRequest;
    +import com.google.pubsub.v1.CreateSnapshotRequest;
    +import com.google.pubsub.v1.DeleteSnapshotRequest;
     import com.google.pubsub.v1.DeleteSubscriptionRequest;
     import com.google.pubsub.v1.GetSubscriptionRequest;
    +import com.google.pubsub.v1.ListSnapshotsRequest;
    +import com.google.pubsub.v1.ListSnapshotsResponse;
     import com.google.pubsub.v1.ListSubscriptionsRequest;
     import com.google.pubsub.v1.ListSubscriptionsResponse;
     import com.google.pubsub.v1.ModifyAckDeadlineRequest;
     import com.google.pubsub.v1.ModifyPushConfigRequest;
     import com.google.pubsub.v1.PullRequest;
     import com.google.pubsub.v1.PullResponse;
    +import com.google.pubsub.v1.SeekRequest;
    +import com.google.pubsub.v1.SeekResponse;
    +import com.google.pubsub.v1.Snapshot;
     import com.google.pubsub.v1.StreamingPullRequest;
     import com.google.pubsub.v1.StreamingPullResponse;
     import com.google.pubsub.v1.SubscriberGrpc;
     import com.google.pubsub.v1.Subscription;
    +import com.google.pubsub.v1.UpdateSubscriptionRequest;
     import io.grpc.Status;
     import java.io.IOException;
     import javax.annotation.Generated;
    @@ -65,7 +75,7 @@
     
     // AUTO-GENERATED DOCUMENTATION AND CLASS
     /**
    - * Settings class to configure an instance of {@link SubscriberClient}.
    + * Settings class to configure an instance of {@link SubscriptionAdminClient}.
      *
      * 

    The default instance has everything set to sensible defaults: * @@ -81,23 +91,17 @@ * *

      * 
    - * SubscriberSettings.Builder subscriberSettingsBuilder =
    - *     SubscriberSettings.defaultBuilder();
    - * subscriberSettingsBuilder.createSubscriptionSettings().getRetrySettingsBuilder()
    + * SubscriptionAdminSettings.Builder subscriptionAdminSettingsBuilder =
    + *     SubscriptionAdminSettings.defaultBuilder();
    + * subscriptionAdminSettingsBuilder.createSubscriptionSettings().getRetrySettingsBuilder()
      *     .setTotalTimeout(Duration.standardSeconds(30));
    - * SubscriberSettings subscriberSettings = subscriberSettingsBuilder.build();
    + * SubscriptionAdminSettings subscriptionAdminSettings = subscriptionAdminSettingsBuilder.build();
      * 
      * 
    */ @Generated("by GAPIC v0.0.5") @ExperimentalApi -public class SubscriberSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "pubsub.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - +public class SubscriptionAdminSettings extends ClientSettings { /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() @@ -108,8 +112,15 @@ public class SubscriberSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final SimpleCallSettings createSubscriptionSettings; private final SimpleCallSettings getSubscriptionSettings; + private final SimpleCallSettings + updateSubscriptionSettings; private final PagedCallSettings< ListSubscriptionsRequest, ListSubscriptionsResponse, ListSubscriptionsPagedResponse> listSubscriptionsSettings; @@ -120,6 +131,12 @@ public class SubscriberSettings extends ClientSettings { private final StreamingCallSettings streamingPullSettings; private final SimpleCallSettings modifyPushConfigSettings; + private final PagedCallSettings< + ListSnapshotsRequest, ListSnapshotsResponse, ListSnapshotsPagedResponse> + listSnapshotsSettings; + private final SimpleCallSettings createSnapshotSettings; + private final SimpleCallSettings deleteSnapshotSettings; + private final SimpleCallSettings seekSettings; private final SimpleCallSettings setIamPolicySettings; private final SimpleCallSettings getIamPolicySettings; private final SimpleCallSettings @@ -135,6 +152,11 @@ public SimpleCallSettings getSubscriptionS return getSubscriptionSettings; } + /** Returns the object with the settings used for calls to updateSubscription. */ + public SimpleCallSettings updateSubscriptionSettings() { + return updateSubscriptionSettings; + } + /** Returns the object with the settings used for calls to listSubscriptions. */ public PagedCallSettings< ListSubscriptionsRequest, ListSubscriptionsResponse, ListSubscriptionsPagedResponse> @@ -173,6 +195,27 @@ public SimpleCallSettings modifyPushConfigSettin return modifyPushConfigSettings; } + /** Returns the object with the settings used for calls to listSnapshots. */ + public PagedCallSettings + listSnapshotsSettings() { + return listSnapshotsSettings; + } + + /** Returns the object with the settings used for calls to createSnapshot. */ + public SimpleCallSettings createSnapshotSettings() { + return createSnapshotSettings; + } + + /** Returns the object with the settings used for calls to deleteSnapshot. */ + public SimpleCallSettings deleteSnapshotSettings() { + return deleteSnapshotSettings; + } + + /** Returns the object with the settings used for calls to seek. */ + public SimpleCallSettings seekSettings() { + return seekSettings; + } + /** Returns the object with the settings used for calls to setIamPolicy. */ public SimpleCallSettings setIamPolicySettings() { return setIamPolicySettings; @@ -194,14 +237,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "pubsub.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -217,15 +255,19 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = SubscriberSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty( + SubscriptionAdminSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ @@ -243,11 +285,12 @@ public Builder toBuilder() { return new Builder(this); } - private SubscriberSettings(Builder settingsBuilder) throws IOException { + private SubscriptionAdminSettings(Builder settingsBuilder) throws IOException { super(settingsBuilder.getExecutorProvider(), settingsBuilder.getChannelProvider()); createSubscriptionSettings = settingsBuilder.createSubscriptionSettings().build(); getSubscriptionSettings = settingsBuilder.getSubscriptionSettings().build(); + updateSubscriptionSettings = settingsBuilder.updateSubscriptionSettings().build(); listSubscriptionsSettings = settingsBuilder.listSubscriptionsSettings().build(); deleteSubscriptionSettings = settingsBuilder.deleteSubscriptionSettings().build(); modifyAckDeadlineSettings = settingsBuilder.modifyAckDeadlineSettings().build(); @@ -255,6 +298,10 @@ private SubscriberSettings(Builder settingsBuilder) throws IOException { pullSettings = settingsBuilder.pullSettings().build(); streamingPullSettings = settingsBuilder.streamingPullSettings().build(); modifyPushConfigSettings = settingsBuilder.modifyPushConfigSettings().build(); + listSnapshotsSettings = settingsBuilder.listSnapshotsSettings().build(); + createSnapshotSettings = settingsBuilder.createSnapshotSettings().build(); + deleteSnapshotSettings = settingsBuilder.deleteSnapshotSettings().build(); + seekSettings = settingsBuilder.seekSettings().build(); setIamPolicySettings = settingsBuilder.setIamPolicySettings().build(); getIamPolicySettings = settingsBuilder.getIamPolicySettings().build(); testIamPermissionsSettings = settingsBuilder.testIamPermissionsSettings().build(); @@ -300,6 +347,40 @@ public Iterable extractResources(ListSubscriptionsResponse payload } }; + private static final PagedListDescriptor + LIST_SNAPSHOTS_PAGE_STR_DESC = + new PagedListDescriptor() { + @Override + public Object emptyToken() { + return ""; + } + + @Override + public ListSnapshotsRequest injectToken(ListSnapshotsRequest payload, Object token) { + return ListSnapshotsRequest.newBuilder(payload).setPageToken((String) token).build(); + } + + @Override + public ListSnapshotsRequest injectPageSize(ListSnapshotsRequest payload, int pageSize) { + return ListSnapshotsRequest.newBuilder(payload).setPageSize(pageSize).build(); + } + + @Override + public Integer extractPageSize(ListSnapshotsRequest payload) { + return payload.getPageSize(); + } + + @Override + public Object extractNextToken(ListSnapshotsResponse payload) { + return payload.getNextPageToken(); + } + + @Override + public Iterable extractResources(ListSnapshotsResponse payload) { + return payload.getSnapshotsList(); + } + }; + private static final PagedListResponseFactory< ListSubscriptionsRequest, ListSubscriptionsResponse, ListSubscriptionsPagedResponse> LIST_SUBSCRIPTIONS_PAGE_STR_FACT = @@ -316,13 +397,30 @@ public ListSubscriptionsPagedResponse createPagedListResponse( } }; - /** Builder for SubscriberSettings. */ + private static final PagedListResponseFactory< + ListSnapshotsRequest, ListSnapshotsResponse, ListSnapshotsPagedResponse> + LIST_SNAPSHOTS_PAGE_STR_FACT = + new PagedListResponseFactory< + ListSnapshotsRequest, ListSnapshotsResponse, ListSnapshotsPagedResponse>() { + @Override + public ListSnapshotsPagedResponse createPagedListResponse( + UnaryCallable callable, + ListSnapshotsRequest request, + CallContext context) { + return new ListSnapshotsPagedResponse( + callable, LIST_SNAPSHOTS_PAGE_STR_DESC, request, context); + } + }; + + /** Builder for SubscriptionAdminSettings. */ public static class Builder extends ClientSettings.Builder { private final ImmutableList unaryMethodSettingsBuilders; private final SimpleCallSettings.Builder createSubscriptionSettings; private final SimpleCallSettings.Builder getSubscriptionSettings; + private final SimpleCallSettings.Builder + updateSubscriptionSettings; private final PagedCallSettings.Builder< ListSubscriptionsRequest, ListSubscriptionsResponse, ListSubscriptionsPagedResponse> listSubscriptionsSettings; @@ -336,6 +434,13 @@ public static class Builder extends ClientSettings.Builder { streamingPullSettings; private final SimpleCallSettings.Builder modifyPushConfigSettings; + private final PagedCallSettings.Builder< + ListSnapshotsRequest, ListSnapshotsResponse, ListSnapshotsPagedResponse> + listSnapshotsSettings; + private final SimpleCallSettings.Builder + createSnapshotSettings; + private final SimpleCallSettings.Builder deleteSnapshotSettings; + private final SimpleCallSettings.Builder seekSettings; private final SimpleCallSettings.Builder setIamPolicySettings; private final SimpleCallSettings.Builder getIamPolicySettings; private final SimpleCallSettings.Builder @@ -353,6 +458,15 @@ public static class Builder extends ClientSettings.Builder { definitions.put( "non_idempotent", Sets.immutableEnumSet(Lists.newArrayList(Status.Code.UNAVAILABLE))); + definitions.put( + "pull", + Sets.immutableEnumSet( + Lists.newArrayList( + Status.Code.CANCELLED, + Status.Code.DEADLINE_EXCEEDED, + Status.Code.RESOURCE_EXHAUSTED, + Status.Code.INTERNAL, + Status.Code.UNAVAILABLE))); RETRYABLE_CODE_DEFINITIONS = definitions.build(); } @@ -393,6 +507,9 @@ private Builder() { getSubscriptionSettings = SimpleCallSettings.newBuilder(SubscriberGrpc.METHOD_GET_SUBSCRIPTION); + updateSubscriptionSettings = + SimpleCallSettings.newBuilder(SubscriberGrpc.METHOD_UPDATE_SUBSCRIPTION); + listSubscriptionsSettings = PagedCallSettings.newBuilder( SubscriberGrpc.METHOD_LIST_SUBSCRIPTIONS, LIST_SUBSCRIPTIONS_PAGE_STR_FACT); @@ -413,6 +530,16 @@ private Builder() { modifyPushConfigSettings = SimpleCallSettings.newBuilder(SubscriberGrpc.METHOD_MODIFY_PUSH_CONFIG); + listSnapshotsSettings = + PagedCallSettings.newBuilder( + SubscriberGrpc.METHOD_LIST_SNAPSHOTS, LIST_SNAPSHOTS_PAGE_STR_FACT); + + createSnapshotSettings = SimpleCallSettings.newBuilder(SubscriberGrpc.METHOD_CREATE_SNAPSHOT); + + deleteSnapshotSettings = SimpleCallSettings.newBuilder(SubscriberGrpc.METHOD_DELETE_SNAPSHOT); + + seekSettings = SimpleCallSettings.newBuilder(SubscriberGrpc.METHOD_SEEK); + setIamPolicySettings = SimpleCallSettings.newBuilder(IAMPolicyGrpc.METHOD_SET_IAM_POLICY); getIamPolicySettings = SimpleCallSettings.newBuilder(IAMPolicyGrpc.METHOD_GET_IAM_POLICY); @@ -424,12 +551,17 @@ private Builder() { ImmutableList.of( createSubscriptionSettings, getSubscriptionSettings, + updateSubscriptionSettings, listSubscriptionsSettings, deleteSubscriptionSettings, modifyAckDeadlineSettings, acknowledgeSettings, pullSettings, modifyPushConfigSettings, + listSnapshotsSettings, + createSnapshotSettings, + deleteSnapshotSettings, + seekSettings, setIamPolicySettings, getIamPolicySettings, testIamPermissionsSettings); @@ -448,6 +580,11 @@ private static Builder createDefault() { .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + builder + .updateSubscriptionSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + builder .listSubscriptionsSettings() .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) @@ -470,7 +607,7 @@ private static Builder createDefault() { builder .pullSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("pull")) .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("messaging")); builder @@ -478,6 +615,26 @@ private static Builder createDefault() { .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + builder + .listSnapshotsSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder + .createSnapshotSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder + .deleteSnapshotSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder + .seekSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + builder .setIamPolicySettings() .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) @@ -496,11 +653,12 @@ private static Builder createDefault() { return builder; } - private Builder(SubscriberSettings settings) { + private Builder(SubscriptionAdminSettings settings) { super(settings); createSubscriptionSettings = settings.createSubscriptionSettings.toBuilder(); getSubscriptionSettings = settings.getSubscriptionSettings.toBuilder(); + updateSubscriptionSettings = settings.updateSubscriptionSettings.toBuilder(); listSubscriptionsSettings = settings.listSubscriptionsSettings.toBuilder(); deleteSubscriptionSettings = settings.deleteSubscriptionSettings.toBuilder(); modifyAckDeadlineSettings = settings.modifyAckDeadlineSettings.toBuilder(); @@ -508,6 +666,10 @@ private Builder(SubscriberSettings settings) { pullSettings = settings.pullSettings.toBuilder(); streamingPullSettings = settings.streamingPullSettings.toBuilder(); modifyPushConfigSettings = settings.modifyPushConfigSettings.toBuilder(); + listSnapshotsSettings = settings.listSnapshotsSettings.toBuilder(); + createSnapshotSettings = settings.createSnapshotSettings.toBuilder(); + deleteSnapshotSettings = settings.deleteSnapshotSettings.toBuilder(); + seekSettings = settings.seekSettings.toBuilder(); setIamPolicySettings = settings.setIamPolicySettings.toBuilder(); getIamPolicySettings = settings.getIamPolicySettings.toBuilder(); testIamPermissionsSettings = settings.testIamPermissionsSettings.toBuilder(); @@ -516,12 +678,17 @@ private Builder(SubscriberSettings settings) { ImmutableList.of( createSubscriptionSettings, getSubscriptionSettings, + updateSubscriptionSettings, listSubscriptionsSettings, deleteSubscriptionSettings, modifyAckDeadlineSettings, acknowledgeSettings, pullSettings, modifyPushConfigSettings, + listSnapshotsSettings, + createSnapshotSettings, + deleteSnapshotSettings, + seekSettings, setIamPolicySettings, getIamPolicySettings, testIamPermissionsSettings); @@ -562,6 +729,12 @@ public SimpleCallSettings.Builder createSubscription return getSubscriptionSettings; } + /** Returns the builder for the settings used for calls to updateSubscription. */ + public SimpleCallSettings.Builder + updateSubscriptionSettings() { + return updateSubscriptionSettings; + } + /** Returns the builder for the settings used for calls to listSubscriptions. */ public PagedCallSettings.Builder< ListSubscriptionsRequest, ListSubscriptionsResponse, ListSubscriptionsPagedResponse> @@ -601,6 +774,28 @@ public SimpleCallSettings.Builder modifyPushConf return modifyPushConfigSettings; } + /** Returns the builder for the settings used for calls to listSnapshots. */ + public PagedCallSettings.Builder< + ListSnapshotsRequest, ListSnapshotsResponse, ListSnapshotsPagedResponse> + listSnapshotsSettings() { + return listSnapshotsSettings; + } + + /** Returns the builder for the settings used for calls to createSnapshot. */ + public SimpleCallSettings.Builder createSnapshotSettings() { + return createSnapshotSettings; + } + + /** Returns the builder for the settings used for calls to deleteSnapshot. */ + public SimpleCallSettings.Builder deleteSnapshotSettings() { + return deleteSnapshotSettings; + } + + /** Returns the builder for the settings used for calls to seek. */ + public SimpleCallSettings.Builder seekSettings() { + return seekSettings; + } + /** Returns the builder for the settings used for calls to setIamPolicy. */ public SimpleCallSettings.Builder setIamPolicySettings() { return setIamPolicySettings; @@ -618,8 +813,8 @@ public SimpleCallSettings.Builder getIamPolicySetti } @Override - public SubscriberSettings build() throws IOException { - return new SubscriberSettings(this); + public SubscriptionAdminSettings build() throws IOException { + return new SubscriptionAdminSettings(this); } } } diff --git a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PublisherClient.java b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/TopicAdminClient.java similarity index 83% rename from google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PublisherClient.java rename to google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/TopicAdminClient.java index ffb576048316..5212f2844096 100644 --- a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PublisherClient.java +++ b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/TopicAdminClient.java @@ -59,14 +59,14 @@ * *
      * 
    - * try (PublisherClient publisherClient = PublisherClient.create()) {
    + * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
      *   TopicName name = TopicName.create("[PROJECT]", "[TOPIC]");
    - *   Topic response = publisherClient.createTopic(name);
    + *   Topic response = topicAdminClient.createTopic(name);
      * }
      * 
      * 
    * - *

    Note: close() needs to be called on the publisherClient object to clean up resources such as + *

    Note: close() needs to be called on the topicAdminClient object to clean up resources such as * threads. In the example above, try-with-resources is used, which automatically calls close(). * *

    The surface of this class includes several types of Java methods for each of the API's @@ -89,26 +89,26 @@ * these names, this class includes a format method for each type of name, and additionally a parse * method to extract the individual identifiers contained within names that are returned. * - *

    This class can be customized by passing in a custom instance of PublisherSettings to create(). - * For example: + *

    This class can be customized by passing in a custom instance of TopicAdminSettings to + * create(). For example: * *

      * 
      * InstantiatingChannelProvider channelProvider =
    - *     PublisherSettings.defaultChannelProviderBuilder()
    + *     TopicAdminSettings.defaultChannelProviderBuilder()
      *         .setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
      *         .build();
    - * PublisherSettings publisherSettings =
    - *     PublisherSettings.defaultBuilder().setChannelProvider(channelProvider).build();
    - * PublisherClient publisherClient =
    - *     PublisherClient.create(publisherSettings);
    + * TopicAdminSettings topicAdminSettings =
    + *     TopicAdminSettings.defaultBuilder().setChannelProvider(channelProvider).build();
    + * TopicAdminClient topicAdminClient =
    + *     TopicAdminClient.create(topicAdminSettings);
      * 
      * 
    */ @Generated("by GAPIC") @ExperimentalApi -public class PublisherClient implements AutoCloseable { - private final PublisherSettings settings; +public class TopicAdminClient implements AutoCloseable { + private final TopicAdminSettings settings; private final ScheduledExecutorService executor; private final ManagedChannel channel; private final List closeables = new ArrayList<>(); @@ -128,24 +128,24 @@ public class PublisherClient implements AutoCloseable { private final UnaryCallable testIamPermissionsCallable; - /** Constructs an instance of PublisherClient with default settings. */ - public static final PublisherClient create() throws IOException { - return create(PublisherSettings.defaultBuilder().build()); + /** Constructs an instance of TopicAdminClient with default settings. */ + public static final TopicAdminClient create() throws IOException { + return create(TopicAdminSettings.defaultBuilder().build()); } /** - * Constructs an instance of PublisherClient, using the given settings. The channels are created + * Constructs an instance of TopicAdminClient, using the given settings. The channels are created * based on the settings passed in, or defaults for any settings that are not set. */ - public static final PublisherClient create(PublisherSettings settings) throws IOException { - return new PublisherClient(settings); + public static final TopicAdminClient create(TopicAdminSettings settings) throws IOException { + return new TopicAdminClient(settings); } /** - * Constructs an instance of PublisherClient, using the given settings. This is protected so that + * Constructs an instance of TopicAdminClient, using the given settings. This is protected so that * it easy to make a subclass, but otherwise, the static factory methods should be preferred. */ - protected PublisherClient(PublisherSettings settings) throws IOException { + protected TopicAdminClient(TopicAdminSettings settings) throws IOException { this.settings = settings; ChannelAndExecutor channelAndExecutor = settings.getChannelAndExecutor(); this.executor = channelAndExecutor.getExecutor(); @@ -197,7 +197,7 @@ public void close() throws IOException { } } - public final PublisherSettings getSettings() { + public final TopicAdminSettings getSettings() { return settings; } @@ -208,9 +208,9 @@ public final PublisherSettings getSettings() { *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName name = TopicName.create("[PROJECT]", "[TOPIC]");
    -   *   Topic response = publisherClient.createTopic(name);
    +   *   Topic response = topicAdminClient.createTopic(name);
        * }
        * 
    * @@ -234,12 +234,12 @@ public final Topic createTopic(TopicName name) { *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName name = TopicName.create("[PROJECT]", "[TOPIC]");
        *   Topic request = Topic.newBuilder()
        *     .setNameWithTopicName(name)
        *     .build();
    -   *   Topic response = publisherClient.createTopic(request);
    +   *   Topic response = topicAdminClient.createTopic(request);
        * }
        * 
    * @@ -257,12 +257,12 @@ private final Topic createTopic(Topic request) { *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName name = TopicName.create("[PROJECT]", "[TOPIC]");
        *   Topic request = Topic.newBuilder()
        *     .setNameWithTopicName(name)
        *     .build();
    -   *   ApiFuture<Topic> future = publisherClient.createTopicCallable().futureCall(request);
    +   *   ApiFuture<Topic> future = topicAdminClient.createTopicCallable().futureCall(request);
        *   // Do something
        *   Topic response = future.get();
        * }
    @@ -281,14 +281,14 @@ public final UnaryCallable createTopicCallable() {
        * 

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
        *   ByteString data = ByteString.copyFromUtf8("");
        *   PubsubMessage messagesElement = PubsubMessage.newBuilder()
        *     .setData(data)
        *     .build();
        *   List<PubsubMessage> messages = Arrays.asList(messagesElement);
    -   *   PublishResponse response = publisherClient.publish(topic, messages);
    +   *   PublishResponse response = topicAdminClient.publish(topic, messages);
        * }
        * 
    * @@ -297,8 +297,8 @@ public final UnaryCallable createTopicCallable() { * @param messages The messages to publish. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - @Deprecated - public final PublishResponse publish(TopicName topic, List messages) { + /* package-private */ final PublishResponse publish( + TopicName topic, List messages) { PublishRequest request = PublishRequest.newBuilder().setTopicWithTopicName(topic).addAllMessages(messages).build(); @@ -314,7 +314,7 @@ public final PublishResponse publish(TopicName topic, List messag *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
        *   ByteString data = ByteString.copyFromUtf8("");
        *   PubsubMessage messagesElement = PubsubMessage.newBuilder()
    @@ -325,15 +325,14 @@ public final PublishResponse publish(TopicName topic, List messag
        *     .setTopicWithTopicName(topic)
        *     .addAllMessages(messages)
        *     .build();
    -   *   PublishResponse response = publisherClient.publish(request);
    +   *   PublishResponse response = topicAdminClient.publish(request);
        * }
        * 
    * * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - @Deprecated - public final PublishResponse publish(PublishRequest request) { + /* package-private */ final PublishResponse publish(PublishRequest request) { return publishCallable().call(request); } @@ -346,7 +345,7 @@ public final PublishResponse publish(PublishRequest request) { *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
        *   ByteString data = ByteString.copyFromUtf8("");
        *   PubsubMessage messagesElement = PubsubMessage.newBuilder()
    @@ -357,14 +356,13 @@ public final PublishResponse publish(PublishRequest request) {
        *     .setTopicWithTopicName(topic)
        *     .addAllMessages(messages)
        *     .build();
    -   *   ApiFuture<PublishResponse> future = publisherClient.publishCallable().futureCall(request);
    +   *   ApiFuture<PublishResponse> future = topicAdminClient.publishCallable().futureCall(request);
        *   // Do something
        *   PublishResponse response = future.get();
        * }
        * 
    */ - @Deprecated - public final UnaryCallable publishCallable() { + /* package-private */ final UnaryCallable publishCallable() { return publishCallable; } @@ -375,9 +373,9 @@ public final UnaryCallable publishCallable() { *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
    -   *   Topic response = publisherClient.getTopic(topic);
    +   *   Topic response = topicAdminClient.getTopic(topic);
        * }
        * 
    * @@ -397,12 +395,12 @@ public final Topic getTopic(TopicName topic) { *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
        *   GetTopicRequest request = GetTopicRequest.newBuilder()
        *     .setTopicWithTopicName(topic)
        *     .build();
    -   *   Topic response = publisherClient.getTopic(request);
    +   *   Topic response = topicAdminClient.getTopic(request);
        * }
        * 
    * @@ -420,12 +418,12 @@ private final Topic getTopic(GetTopicRequest request) { *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
        *   GetTopicRequest request = GetTopicRequest.newBuilder()
        *     .setTopicWithTopicName(topic)
        *     .build();
    -   *   ApiFuture<Topic> future = publisherClient.getTopicCallable().futureCall(request);
    +   *   ApiFuture<Topic> future = topicAdminClient.getTopicCallable().futureCall(request);
        *   // Do something
        *   Topic response = future.get();
        * }
    @@ -442,9 +440,9 @@ public final UnaryCallable getTopicCallable() {
        * 

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   ProjectName project = ProjectName.create("[PROJECT]");
    -   *   for (Topic element : publisherClient.listTopics(project).iterateAllElements()) {
    +   *   for (Topic element : topicAdminClient.listTopics(project).iterateAllElements()) {
        *     // doThingsWith(element);
        *   }
        * }
    @@ -467,12 +465,12 @@ public final ListTopicsPagedResponse listTopics(ProjectName project) {
        * 

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   ProjectName project = ProjectName.create("[PROJECT]");
        *   ListTopicsRequest request = ListTopicsRequest.newBuilder()
        *     .setProjectWithProjectName(project)
        *     .build();
    -   *   for (Topic element : publisherClient.listTopics(request).iterateAllElements()) {
    +   *   for (Topic element : topicAdminClient.listTopics(request).iterateAllElements()) {
        *     // doThingsWith(element);
        *   }
        * }
    @@ -492,12 +490,12 @@ public final ListTopicsPagedResponse listTopics(ListTopicsRequest request) {
        * 

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   ProjectName project = ProjectName.create("[PROJECT]");
        *   ListTopicsRequest request = ListTopicsRequest.newBuilder()
        *     .setProjectWithProjectName(project)
        *     .build();
    -   *   ApiFuture<ListTopicsPagedResponse> future = publisherClient.listTopicsPagedCallable().futureCall(request);
    +   *   ApiFuture<ListTopicsPagedResponse> future = topicAdminClient.listTopicsPagedCallable().futureCall(request);
        *   // Do something
        *   for (Topic element : future.get().iterateAllElements()) {
        *     // doThingsWith(element);
    @@ -516,13 +514,13 @@ public final UnaryCallable listTopic
        * 

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   ProjectName project = ProjectName.create("[PROJECT]");
        *   ListTopicsRequest request = ListTopicsRequest.newBuilder()
        *     .setProjectWithProjectName(project)
        *     .build();
        *   while (true) {
    -   *     ListTopicsResponse response = publisherClient.listTopicsCallable().call(request);
    +   *     ListTopicsResponse response = topicAdminClient.listTopicsCallable().call(request);
        *     for (Topic element : response.getTopicsList()) {
        *       // doThingsWith(element);
        *     }
    @@ -547,9 +545,9 @@ public final UnaryCallable listTopicsCall
        * 

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
    -   *   for (SubscriptionName element : publisherClient.listTopicSubscriptions(topic).iterateAllAsSubscriptionName()) {
    +   *   for (SubscriptionName element : topicAdminClient.listTopicSubscriptions(topic).iterateAllAsSubscriptionName()) {
        *     // doThingsWith(element);
        *   }
        * }
    @@ -572,12 +570,12 @@ public final ListTopicSubscriptionsPagedResponse listTopicSubscriptions(TopicNam
        * 

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
        *   ListTopicSubscriptionsRequest request = ListTopicSubscriptionsRequest.newBuilder()
        *     .setTopicWithTopicName(topic)
        *     .build();
    -   *   for (SubscriptionName element : publisherClient.listTopicSubscriptions(request).iterateAllAsSubscriptionName()) {
    +   *   for (SubscriptionName element : topicAdminClient.listTopicSubscriptions(request).iterateAllAsSubscriptionName()) {
        *     // doThingsWith(element);
        *   }
        * }
    @@ -598,12 +596,12 @@ public final ListTopicSubscriptionsPagedResponse listTopicSubscriptions(
        * 

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
        *   ListTopicSubscriptionsRequest request = ListTopicSubscriptionsRequest.newBuilder()
        *     .setTopicWithTopicName(topic)
        *     .build();
    -   *   ApiFuture<ListTopicSubscriptionsPagedResponse> future = publisherClient.listTopicSubscriptionsPagedCallable().futureCall(request);
    +   *   ApiFuture<ListTopicSubscriptionsPagedResponse> future = topicAdminClient.listTopicSubscriptionsPagedCallable().futureCall(request);
        *   // Do something
        *   for (SubscriptionName element : future.get().iterateAllAsSubscriptionName()) {
        *     // doThingsWith(element);
    @@ -623,13 +621,13 @@ public final ListTopicSubscriptionsPagedResponse listTopicSubscriptions(
        * 

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
        *   ListTopicSubscriptionsRequest request = ListTopicSubscriptionsRequest.newBuilder()
        *     .setTopicWithTopicName(topic)
        *     .build();
        *   while (true) {
    -   *     ListTopicSubscriptionsResponse response = publisherClient.listTopicSubscriptionsCallable().call(request);
    +   *     ListTopicSubscriptionsResponse response = topicAdminClient.listTopicSubscriptionsCallable().call(request);
        *     for (SubscriptionName element : response.getSubscriptionsListAsSubscriptionNameList()) {
        *       // doThingsWith(element);
        *     }
    @@ -658,9 +656,9 @@ public final ListTopicSubscriptionsPagedResponse listTopicSubscriptions(
        * 

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
    -   *   publisherClient.deleteTopic(topic);
    +   *   topicAdminClient.deleteTopic(topic);
        * }
        * 
    * @@ -684,12 +682,12 @@ public final void deleteTopic(TopicName topic) { *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
        *   DeleteTopicRequest request = DeleteTopicRequest.newBuilder()
        *     .setTopicWithTopicName(topic)
        *     .build();
    -   *   publisherClient.deleteTopic(request);
    +   *   topicAdminClient.deleteTopic(request);
        * }
        * 
    * @@ -710,12 +708,12 @@ private final void deleteTopic(DeleteTopicRequest request) { *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
        *   DeleteTopicRequest request = DeleteTopicRequest.newBuilder()
        *     .setTopicWithTopicName(topic)
        *     .build();
    -   *   ApiFuture<Void> future = publisherClient.deleteTopicCallable().futureCall(request);
    +   *   ApiFuture<Void> future = topicAdminClient.deleteTopicCallable().futureCall(request);
        *   // Do something
        *   future.get();
        * }
    @@ -732,10 +730,10 @@ public final UnaryCallable deleteTopicCallable() {
        * 

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   String formattedResource = TopicName.create("[PROJECT]", "[TOPIC]").toString();
        *   Policy policy = Policy.newBuilder().build();
    -   *   Policy response = publisherClient.setIamPolicy(formattedResource, policy);
    +   *   Policy response = topicAdminClient.setIamPolicy(formattedResource, policy);
        * }
        * 
    * @@ -761,14 +759,14 @@ public final Policy setIamPolicy(String resource, Policy policy) { *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   String formattedResource = TopicName.create("[PROJECT]", "[TOPIC]").toString();
        *   Policy policy = Policy.newBuilder().build();
        *   SetIamPolicyRequest request = SetIamPolicyRequest.newBuilder()
        *     .setResource(formattedResource)
        *     .setPolicy(policy)
        *     .build();
    -   *   Policy response = publisherClient.setIamPolicy(request);
    +   *   Policy response = topicAdminClient.setIamPolicy(request);
        * }
        * 
    * @@ -786,14 +784,14 @@ public final Policy setIamPolicy(SetIamPolicyRequest request) { *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   String formattedResource = TopicName.create("[PROJECT]", "[TOPIC]").toString();
        *   Policy policy = Policy.newBuilder().build();
        *   SetIamPolicyRequest request = SetIamPolicyRequest.newBuilder()
        *     .setResource(formattedResource)
        *     .setPolicy(policy)
        *     .build();
    -   *   ApiFuture<Policy> future = publisherClient.setIamPolicyCallable().futureCall(request);
    +   *   ApiFuture<Policy> future = topicAdminClient.setIamPolicyCallable().futureCall(request);
        *   // Do something
        *   Policy response = future.get();
        * }
    @@ -811,9 +809,9 @@ public final UnaryCallable setIamPolicyCallable() {
        * 

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   String formattedResource = TopicName.create("[PROJECT]", "[TOPIC]").toString();
    -   *   Policy response = publisherClient.getIamPolicy(formattedResource);
    +   *   Policy response = topicAdminClient.getIamPolicy(formattedResource);
        * }
        * 
    * @@ -836,12 +834,12 @@ public final Policy getIamPolicy(String resource) { *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   String formattedResource = TopicName.create("[PROJECT]", "[TOPIC]").toString();
        *   GetIamPolicyRequest request = GetIamPolicyRequest.newBuilder()
        *     .setResource(formattedResource)
        *     .build();
    -   *   Policy response = publisherClient.getIamPolicy(request);
    +   *   Policy response = topicAdminClient.getIamPolicy(request);
        * }
        * 
    * @@ -860,12 +858,12 @@ private final Policy getIamPolicy(GetIamPolicyRequest request) { *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   String formattedResource = TopicName.create("[PROJECT]", "[TOPIC]").toString();
        *   GetIamPolicyRequest request = GetIamPolicyRequest.newBuilder()
        *     .setResource(formattedResource)
        *     .build();
    -   *   ApiFuture<Policy> future = publisherClient.getIamPolicyCallable().futureCall(request);
    +   *   ApiFuture<Policy> future = topicAdminClient.getIamPolicyCallable().futureCall(request);
        *   // Do something
        *   Policy response = future.get();
        * }
    @@ -883,10 +881,10 @@ public final UnaryCallable getIamPolicyCallable() {
        * 

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   String formattedResource = TopicName.create("[PROJECT]", "[TOPIC]").toString();
        *   List<String> permissions = new ArrayList<>();
    -   *   TestIamPermissionsResponse response = publisherClient.testIamPermissions(formattedResource, permissions);
    +   *   TestIamPermissionsResponse response = topicAdminClient.testIamPermissions(formattedResource, permissions);
        * }
        * 
    * @@ -917,14 +915,14 @@ public final TestIamPermissionsResponse testIamPermissions( *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   String formattedResource = TopicName.create("[PROJECT]", "[TOPIC]").toString();
        *   List<String> permissions = new ArrayList<>();
        *   TestIamPermissionsRequest request = TestIamPermissionsRequest.newBuilder()
        *     .setResource(formattedResource)
        *     .addAllPermissions(permissions)
        *     .build();
    -   *   TestIamPermissionsResponse response = publisherClient.testIamPermissions(request);
    +   *   TestIamPermissionsResponse response = topicAdminClient.testIamPermissions(request);
        * }
        * 
    * @@ -943,14 +941,14 @@ public final TestIamPermissionsResponse testIamPermissions(TestIamPermissionsReq *

    Sample code: * *

    
    -   * try (PublisherClient publisherClient = PublisherClient.create()) {
    +   * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
        *   String formattedResource = TopicName.create("[PROJECT]", "[TOPIC]").toString();
        *   List<String> permissions = new ArrayList<>();
        *   TestIamPermissionsRequest request = TestIamPermissionsRequest.newBuilder()
        *     .setResource(formattedResource)
        *     .addAllPermissions(permissions)
        *     .build();
    -   *   ApiFuture<TestIamPermissionsResponse> future = publisherClient.testIamPermissionsCallable().futureCall(request);
    +   *   ApiFuture<TestIamPermissionsResponse> future = topicAdminClient.testIamPermissionsCallable().futureCall(request);
        *   // Do something
        *   TestIamPermissionsResponse response = future.get();
        * }
    diff --git a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PublisherSettings.java b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/TopicAdminSettings.java
    similarity index 93%
    rename from google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PublisherSettings.java
    rename to google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/TopicAdminSettings.java
    index c189d29d46fd..9a98247b0985 100644
    --- a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/PublisherSettings.java
    +++ b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/TopicAdminSettings.java
    @@ -19,10 +19,12 @@
     import static com.google.cloud.pubsub.spi.v1.PagedResponseWrappers.ListTopicsPagedResponse;
     
     import com.google.api.gax.batching.BatchingSettings;
    +import com.google.api.gax.batching.PartitionKey;
     import com.google.api.gax.batching.RequestBuilder;
     import com.google.api.gax.core.FlowControlSettings;
     import com.google.api.gax.core.FlowController.LimitExceededBehavior;
     import com.google.api.gax.core.GoogleCredentialsProvider;
    +import com.google.api.gax.core.PropertiesProvider;
     import com.google.api.gax.core.RetrySettings;
     import com.google.api.gax.grpc.BatchedRequestIssuer;
     import com.google.api.gax.grpc.BatchingCallSettings;
    @@ -72,7 +74,7 @@
     
     // AUTO-GENERATED DOCUMENTATION AND CLASS
     /**
    - * Settings class to configure an instance of {@link PublisherClient}.
    + * Settings class to configure an instance of {@link TopicAdminClient}.
      *
      * 

    The default instance has everything set to sensible defaults: * @@ -88,23 +90,17 @@ * *

      * 
    - * PublisherSettings.Builder publisherSettingsBuilder =
    - *     PublisherSettings.defaultBuilder();
    - * publisherSettingsBuilder.createTopicSettings().getRetrySettingsBuilder()
    + * TopicAdminSettings.Builder topicAdminSettingsBuilder =
    + *     TopicAdminSettings.defaultBuilder();
    + * topicAdminSettingsBuilder.createTopicSettings().getRetrySettingsBuilder()
      *     .setTotalTimeout(Duration.standardSeconds(30));
    - * PublisherSettings publisherSettings = publisherSettingsBuilder.build();
    + * TopicAdminSettings topicAdminSettings = topicAdminSettingsBuilder.build();
      * 
      * 
    */ @Generated("by GAPIC v0.0.5") @ExperimentalApi -public class PublisherSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "pubsub.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - +public class TopicAdminSettings extends ClientSettings { /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() @@ -115,6 +111,11 @@ public class PublisherSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final SimpleCallSettings createTopicSettings; private final BatchingCallSettings publishSettings; private final SimpleCallSettings getTopicSettings; @@ -185,14 +186,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "pubsub.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -208,15 +204,19 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = PublisherSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty( + TopicAdminSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ @@ -234,7 +234,7 @@ public Builder toBuilder() { return new Builder(this); } - private PublisherSettings(Builder settingsBuilder) throws IOException { + private TopicAdminSettings(Builder settingsBuilder) throws IOException { super(settingsBuilder.getExecutorProvider(), settingsBuilder.getChannelProvider()); createTopicSettings = settingsBuilder.createTopicSettings().build(); @@ -360,8 +360,8 @@ public ListTopicSubscriptionsPagedResponse createPagedListResponse( private static final BatchingDescriptor PUBLISH_BATCHING_DESC = new BatchingDescriptor() { @Override - public String getBatchPartitionKey(PublishRequest request) { - return request.getTopic() + "|"; + public PartitionKey getBatchPartitionKey(PublishRequest request) { + return new PartitionKey(request.getTopic()); } @Override @@ -423,7 +423,7 @@ public long countBytes(PublishRequest request) { } }; - /** Builder for PublisherSettings. */ + /** Builder for TopicAdminSettings. */ public static class Builder extends ClientSettings.Builder { private final ImmutableList unaryMethodSettingsBuilders; @@ -456,7 +456,13 @@ public static class Builder extends ClientSettings.Builder { "one_plus_delivery", Sets.immutableEnumSet( Lists.newArrayList( - Status.Code.DEADLINE_EXCEEDED, Status.Code.UNAVAILABLE))); + Status.Code.CANCELLED, + Status.Code.UNKNOWN, + Status.Code.DEADLINE_EXCEEDED, + Status.Code.RESOURCE_EXHAUSTED, + Status.Code.ABORTED, + Status.Code.INTERNAL, + Status.Code.UNAVAILABLE))); definitions.put( "non_idempotent", Sets.immutableEnumSet(Lists.newArrayList(Status.Code.UNAVAILABLE))); @@ -593,7 +599,7 @@ private static Builder createDefault() { return builder; } - private Builder(PublisherSettings settings) { + private Builder(TopicAdminSettings settings) { super(settings); createTopicSettings = settings.createTopicSettings.toBuilder(); @@ -694,8 +700,8 @@ public SimpleCallSettings.Builder getIamPolicySetti } @Override - public PublisherSettings build() throws IOException { - return new PublisherSettings(this); + public TopicAdminSettings build() throws IOException { + return new TopicAdminSettings(this); } } } diff --git a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/package-info.java b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/package-info.java index e7beb741eb31..4054800fd344 100644 --- a/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/package-info.java +++ b/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/package-info.java @@ -19,41 +19,41 @@ * *

    The interfaces provided are listed below, along with usage samples. * - *

    =============== PublisherClient =============== + *

    ================ TopicAdminClient ================ * *

    Service Description: The service that an application uses to manipulate topics, and to send * messages to a topic. * *

    To publish messages to a topic, see the Publisher class. * - *

    Sample for PublisherClient: + *

    Sample for TopicAdminClient: * *

      * 
    - * try (PublisherClient publisherClient = PublisherClient.create()) {
    + * try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
      *   TopicName name = TopicName.create("[PROJECT]", "[TOPIC]");
    - *   Topic response = publisherClient.createTopic(name);
    + *   Topic response = topicAdminClient.createTopic(name);
      * }
      * 
      * 
    * - * ================ SubscriberClient ================ + * ======================= SubscriptionAdminClient ======================= * *

    Service Description: The service that an application uses to manipulate subscriptions and to * consume messages from a subscription via the `Pull` method. * *

    To retrieve messages from a subscription, see the Subscriber class. * - *

    Sample for SubscriberClient: + *

    Sample for SubscriptionAdminClient: * *

      * 
    - * try (SubscriberClient subscriberClient = SubscriberClient.create()) {
    + * try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
      *   SubscriptionName name = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]");
      *   TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]");
      *   PushConfig pushConfig = PushConfig.newBuilder().build();
      *   int ackDeadlineSeconds = 0;
    - *   Subscription response = subscriberClient.createSubscription(name, topic, pushConfig, ackDeadlineSeconds);
    + *   Subscription response = subscriptionAdminClient.createSubscription(name, topic, pushConfig, ackDeadlineSeconds);
      * }
      * 
      * 
    diff --git a/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/it/ITPubSubTest.java b/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/it/ITPubSubTest.java index ae6a704a9778..eba7a6eedc48 100644 --- a/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/it/ITPubSubTest.java +++ b/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/it/ITPubSubTest.java @@ -25,9 +25,9 @@ import com.google.cloud.pubsub.spi.v1.AckReplyConsumer; import com.google.cloud.pubsub.spi.v1.MessageReceiver; import com.google.cloud.pubsub.spi.v1.Publisher; -import com.google.cloud.pubsub.spi.v1.PublisherClient; import com.google.cloud.pubsub.spi.v1.Subscriber; -import com.google.cloud.pubsub.spi.v1.SubscriberClient; +import com.google.cloud.pubsub.spi.v1.SubscriptionAdminClient; +import com.google.cloud.pubsub.spi.v1.TopicAdminClient; import com.google.common.util.concurrent.MoreExecutors; import com.google.iam.v1.Binding; import com.google.iam.v1.Policy; @@ -48,23 +48,23 @@ public class ITPubSubTest { private static final String NAME_SUFFIX = UUID.randomUUID().toString(); - private static PublisherClient publisherClient; - private static SubscriberClient subscriberClient; + private static TopicAdminClient topicAdminClient; + private static SubscriptionAdminClient subscriptionAdminClient; private static String projectId; @Rule public Timeout globalTimeout = Timeout.seconds(300); @BeforeClass public static void setupClass() throws Exception { - publisherClient = PublisherClient.create(); - subscriberClient = SubscriberClient.create(); + topicAdminClient = TopicAdminClient.create(); + subscriptionAdminClient = SubscriptionAdminClient.create(); projectId = ServiceOptions.getDefaultProjectId(); } @AfterClass public static void tearDownClass() throws Exception { - publisherClient.close(); - subscriberClient.close(); + topicAdminClient.close(); + subscriptionAdminClient.close(); } private String formatForTest(String resourceName) { @@ -74,24 +74,24 @@ private String formatForTest(String resourceName) { @Test public void testTopicPolicy() { TopicName topicName = TopicName.create(projectId, formatForTest("testing-topic-policy")); - publisherClient.createTopic(topicName); + topicAdminClient.createTopic(topicName); - Policy policy = publisherClient.getIamPolicy(topicName.toString()); + Policy policy = topicAdminClient.getIamPolicy(topicName.toString()); Binding binding = Binding.newBuilder().setRole("roles/viewer").addMembers("allAuthenticatedUsers").build(); Policy newPolicy = - publisherClient.setIamPolicy( + topicAdminClient.setIamPolicy( topicName.toString(), policy.toBuilder().addBindings(binding).build()); assertTrue(newPolicy.getBindingsList().contains(binding)); String permissionName = "pubsub.topics.get"; List permissions = - publisherClient + topicAdminClient .testIamPermissions(topicName.toString(), Collections.singletonList(permissionName)) .getPermissionsList(); assertTrue(permissions.contains(permissionName)); - publisherClient.deleteTopic(topicName); + topicAdminClient.deleteTopic(topicName); } @Test @@ -101,15 +101,15 @@ public void testPublishSubscribe() throws Exception { SubscriptionName subscriptionName = SubscriptionName.create(projectId, formatForTest("testing-publish-subscribe-subscription")); - publisherClient.createTopic(topicName); - subscriberClient.createSubscription( + topicAdminClient.createTopic(topicName); + subscriptionAdminClient.createSubscription( subscriptionName, topicName, PushConfig.newBuilder().build(), 10); PubsubMessage message = PubsubMessage.newBuilder().setData(ByteString.copyFromUtf8("my message")).build(); final SettableApiFuture received = SettableApiFuture.create(); Subscriber subscriber = - Subscriber.newBuilder( + Subscriber.defaultBuilder( subscriptionName, new MessageReceiver() { @Override @@ -124,7 +124,7 @@ public void receiveMessage( }) .build(); subscriber.addListener( - new Subscriber.SubscriberListener() { + new Subscriber.Listener() { public void failed(Subscriber.State from, Throwable failure) { received.setException(failure); } @@ -132,13 +132,13 @@ public void failed(Subscriber.State from, Throwable failure) { MoreExecutors.directExecutor()); subscriber.startAsync(); - Publisher publisher = Publisher.newBuilder(topicName).build(); + Publisher publisher = Publisher.defaultBuilder(topicName).build(); publisher.publish(message).get(); publisher.shutdown(); assertEquals(received.get().getData(), message.getData()); subscriber.stopAsync().awaitTerminated(); - subscriberClient.deleteSubscription(subscriptionName); - publisherClient.deleteTopic(topicName); + subscriptionAdminClient.deleteSubscription(subscriptionName); + topicAdminClient.deleteTopic(topicName); } } diff --git a/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/MockSubscriberImpl.java b/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/MockSubscriberImpl.java index a7b0077a6bee..e780fb364037 100644 --- a/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/MockSubscriberImpl.java +++ b/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/MockSubscriberImpl.java @@ -18,18 +18,26 @@ import com.google.protobuf.Empty; import com.google.protobuf.GeneratedMessageV3; import com.google.pubsub.v1.AcknowledgeRequest; +import com.google.pubsub.v1.CreateSnapshotRequest; +import com.google.pubsub.v1.DeleteSnapshotRequest; import com.google.pubsub.v1.DeleteSubscriptionRequest; import com.google.pubsub.v1.GetSubscriptionRequest; +import com.google.pubsub.v1.ListSnapshotsRequest; +import com.google.pubsub.v1.ListSnapshotsResponse; import com.google.pubsub.v1.ListSubscriptionsRequest; import com.google.pubsub.v1.ListSubscriptionsResponse; import com.google.pubsub.v1.ModifyAckDeadlineRequest; import com.google.pubsub.v1.ModifyPushConfigRequest; import com.google.pubsub.v1.PullRequest; import com.google.pubsub.v1.PullResponse; +import com.google.pubsub.v1.SeekRequest; +import com.google.pubsub.v1.SeekResponse; +import com.google.pubsub.v1.Snapshot; import com.google.pubsub.v1.StreamingPullRequest; import com.google.pubsub.v1.StreamingPullResponse; import com.google.pubsub.v1.SubscriberGrpc.SubscriberImplBase; import com.google.pubsub.v1.Subscription; +import com.google.pubsub.v1.UpdateSubscriptionRequest; import io.grpc.stub.StreamObserver; import java.util.ArrayList; import java.util.LinkedList; @@ -97,6 +105,21 @@ public void getSubscription( } } + @Override + public void updateSubscription( + UpdateSubscriptionRequest request, StreamObserver responseObserver) { + Object response = responses.remove(); + if (response instanceof Subscription) { + requests.add(request); + responseObserver.onNext((Subscription) response); + responseObserver.onCompleted(); + } else if (response instanceof Exception) { + responseObserver.onError((Exception) response); + } else { + responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); + } + } + @Override public void listSubscriptions( ListSubscriptionsRequest request, @@ -215,4 +238,63 @@ public void modifyPushConfig( responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); } } + + @Override + public void listSnapshots( + ListSnapshotsRequest request, StreamObserver responseObserver) { + Object response = responses.remove(); + if (response instanceof ListSnapshotsResponse) { + requests.add(request); + responseObserver.onNext((ListSnapshotsResponse) response); + responseObserver.onCompleted(); + } else if (response instanceof Exception) { + responseObserver.onError((Exception) response); + } else { + responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); + } + } + + @Override + public void createSnapshot( + CreateSnapshotRequest request, StreamObserver responseObserver) { + Object response = responses.remove(); + if (response instanceof Snapshot) { + requests.add(request); + responseObserver.onNext((Snapshot) response); + responseObserver.onCompleted(); + } else if (response instanceof Exception) { + responseObserver.onError((Exception) response); + } else { + responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); + } + } + + @Override + public void deleteSnapshot( + DeleteSnapshotRequest request, StreamObserver responseObserver) { + Object response = responses.remove(); + if (response instanceof Empty) { + requests.add(request); + responseObserver.onNext((Empty) response); + responseObserver.onCompleted(); + } else if (response instanceof Exception) { + responseObserver.onError((Exception) response); + } else { + responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); + } + } + + @Override + public void seek(SeekRequest request, StreamObserver responseObserver) { + Object response = responses.remove(); + if (response instanceof SeekResponse) { + requests.add(request); + responseObserver.onNext((SeekResponse) response); + responseObserver.onCompleted(); + } else if (response instanceof Exception) { + responseObserver.onError((Exception) response); + } else { + responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); + } + } } diff --git a/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/PublisherImplTest.java b/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/PublisherImplTest.java index 0bfa930887bd..67bc90fa5229 100644 --- a/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/PublisherImplTest.java +++ b/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/PublisherImplTest.java @@ -347,7 +347,7 @@ public void testPublishFailureRetries_nonRetryableFailsImmediately() throws Exce @Test public void testPublisherGetters() throws Exception { - Publisher.Builder builder = Publisher.newBuilder(TEST_TOPIC); + Publisher.Builder builder = Publisher.defaultBuilder(TEST_TOPIC); builder.setChannelProvider(TEST_CHANNEL_PROVIDER); builder.setExecutorProvider(SINGLE_THREAD_EXECUTOR); builder.setBatchingSettings( @@ -378,7 +378,7 @@ public void testPublisherGetters() throws Exception { @Test public void testBuilderParametersAndDefaults() { - Publisher.Builder builder = Publisher.newBuilder(TEST_TOPIC); + Publisher.Builder builder = Publisher.defaultBuilder(TEST_TOPIC); assertEquals(TEST_TOPIC, builder.topicName); assertEquals(Publisher.Builder.DEFAULT_EXECUTOR_PROVIDER, builder.executorProvider); assertEquals( @@ -397,7 +397,7 @@ public void testBuilderParametersAndDefaults() { @Test public void testBuilderInvalidArguments() { - Publisher.Builder builder = Publisher.newBuilder(TEST_TOPIC); + Publisher.Builder builder = Publisher.defaultBuilder(TEST_TOPIC); try { builder.setChannelProvider(null); @@ -587,7 +587,7 @@ public void testBuilderInvalidArguments() { } private Builder getTestPublisherBuilder() { - return Publisher.newBuilder(TEST_TOPIC) + return Publisher.defaultBuilder(TEST_TOPIC) .setExecutorProvider(FixedExecutorProvider.create(fakeExecutor)) .setChannelProvider(TEST_CHANNEL_PROVIDER) .setLongRandom( diff --git a/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/SubscriberImplTest.java b/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/SubscriberImplTest.java index 15f2fe5dc05c..19df0b265fb7 100644 --- a/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/SubscriberImplTest.java +++ b/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/SubscriberImplTest.java @@ -458,7 +458,7 @@ private void sendMessages(Iterable ackIds) throws InterruptedException { } private Builder getTestSubscriberBuilder(MessageReceiver receiver) { - return Subscriber.newBuilder(TEST_SUBSCRIPTION, receiver) + return Subscriber.defaultBuilder(TEST_SUBSCRIPTION, receiver) .setExecutorProvider(FixedExecutorProvider.create(fakeExecutor)) .setCredentials(testCredentials) .setChannelBuilder(testChannelBuilder) diff --git a/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/SubscriberClientTest.java b/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/SubscriptionAdminClientTest.java similarity index 77% rename from google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/SubscriberClientTest.java rename to google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/SubscriptionAdminClientTest.java index 36f9901abc62..8a7705e3ae87 100644 --- a/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/SubscriberClientTest.java +++ b/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/SubscriptionAdminClientTest.java @@ -15,6 +15,7 @@ */ package com.google.cloud.pubsub.spi.v1; +import static com.google.cloud.pubsub.spi.v1.PagedResponseWrappers.ListSnapshotsPagedResponse; import static com.google.cloud.pubsub.spi.v1.PagedResponseWrappers.ListSubscriptionsPagedResponse; import com.google.api.gax.core.ApiStreamObserver; @@ -33,8 +34,12 @@ import com.google.protobuf.Empty; import com.google.protobuf.GeneratedMessageV3; import com.google.pubsub.v1.AcknowledgeRequest; +import com.google.pubsub.v1.CreateSnapshotRequest; +import com.google.pubsub.v1.DeleteSnapshotRequest; import com.google.pubsub.v1.DeleteSubscriptionRequest; import com.google.pubsub.v1.GetSubscriptionRequest; +import com.google.pubsub.v1.ListSnapshotsRequest; +import com.google.pubsub.v1.ListSnapshotsResponse; import com.google.pubsub.v1.ListSubscriptionsRequest; import com.google.pubsub.v1.ListSubscriptionsResponse; import com.google.pubsub.v1.ModifyAckDeadlineRequest; @@ -43,6 +48,8 @@ import com.google.pubsub.v1.PullRequest; import com.google.pubsub.v1.PullResponse; import com.google.pubsub.v1.PushConfig; +import com.google.pubsub.v1.Snapshot; +import com.google.pubsub.v1.SnapshotName; import com.google.pubsub.v1.StreamingPullRequest; import com.google.pubsub.v1.StreamingPullResponse; import com.google.pubsub.v1.Subscription; @@ -64,12 +71,12 @@ import org.junit.Test; @javax.annotation.Generated("by GAPIC") -public class SubscriberClientTest { +public class SubscriptionAdminClientTest { private static MockPublisher mockPublisher; private static MockIAMPolicy mockIAMPolicy; private static MockSubscriber mockSubscriber; private static MockServiceHelper serviceHelper; - private SubscriberClient client; + private SubscriptionAdminClient client; @BeforeClass public static void startStaticServer() { @@ -91,11 +98,11 @@ public static void stopServer() { @Before public void setUp() throws IOException { serviceHelper.reset(); - SubscriberSettings settings = - SubscriberSettings.defaultBuilder() + SubscriptionAdminSettings settings = + SubscriptionAdminSettings.defaultBuilder() .setChannelProvider(serviceHelper.createChannelProvider()) .build(); - client = SubscriberClient.create(settings); + client = SubscriptionAdminClient.create(settings); } @After @@ -109,11 +116,13 @@ public void createSubscriptionTest() { SubscriptionName name2 = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]"); TopicNameOneof topic2 = TopicNameOneof.from(TopicName.create("[PROJECT]", "[TOPIC]")); int ackDeadlineSeconds2 = -921632575; + boolean retainAckedMessages = false; Subscription expectedResponse = Subscription.newBuilder() .setNameWithSubscriptionName(name2) .setTopicWithTopicNameOneof(topic2) .setAckDeadlineSeconds(ackDeadlineSeconds2) + .setRetainAckedMessages(retainAckedMessages) .build(); mockSubscriber.addResponse(expectedResponse); @@ -139,7 +148,7 @@ public void createSubscriptionTest() { @Test @SuppressWarnings("all") public void createSubscriptionExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockSubscriber.addException(exception); try { @@ -151,7 +160,7 @@ public void createSubscriptionExceptionTest() throws Exception { client.createSubscription(name, topic, pushConfig, ackDeadlineSeconds); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -161,11 +170,13 @@ public void getSubscriptionTest() { SubscriptionName name = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]"); TopicNameOneof topic = TopicNameOneof.from(TopicName.create("[PROJECT]", "[TOPIC]")); int ackDeadlineSeconds = 2135351438; + boolean retainAckedMessages = false; Subscription expectedResponse = Subscription.newBuilder() .setNameWithSubscriptionName(name) .setTopicWithTopicNameOneof(topic) .setAckDeadlineSeconds(ackDeadlineSeconds) + .setRetainAckedMessages(retainAckedMessages) .build(); mockSubscriber.addResponse(expectedResponse); @@ -184,7 +195,7 @@ public void getSubscriptionTest() { @Test @SuppressWarnings("all") public void getSubscriptionExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockSubscriber.addException(exception); try { @@ -193,7 +204,7 @@ public void getSubscriptionExceptionTest() throws Exception { client.getSubscription(subscription); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -228,7 +239,7 @@ public void listSubscriptionsTest() { @Test @SuppressWarnings("all") public void listSubscriptionsExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockSubscriber.addException(exception); try { @@ -237,7 +248,7 @@ public void listSubscriptionsExceptionTest() throws Exception { client.listSubscriptions(project); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -261,7 +272,7 @@ public void deleteSubscriptionTest() { @Test @SuppressWarnings("all") public void deleteSubscriptionExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockSubscriber.addException(exception); try { @@ -270,7 +281,7 @@ public void deleteSubscriptionExceptionTest() throws Exception { client.deleteSubscription(subscription); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -298,7 +309,7 @@ public void modifyAckDeadlineTest() { @Test @SuppressWarnings("all") public void modifyAckDeadlineExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockSubscriber.addException(exception); try { @@ -309,7 +320,7 @@ public void modifyAckDeadlineExceptionTest() throws Exception { client.modifyAckDeadline(subscription, ackIds, ackDeadlineSeconds); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -335,7 +346,7 @@ public void acknowledgeTest() { @Test @SuppressWarnings("all") public void acknowledgeExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockSubscriber.addException(exception); try { @@ -345,7 +356,7 @@ public void acknowledgeExceptionTest() throws Exception { client.acknowledge(subscription, ackIds); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -374,7 +385,7 @@ public void pullTest() { @Test @SuppressWarnings("all") public void pullExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockSubscriber.addException(exception); try { @@ -385,7 +396,7 @@ public void pullExceptionTest() throws Exception { client.pull(subscription, returnImmediately, maxMessages); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -420,7 +431,7 @@ public void streamingPullTest() throws Exception { @Test @SuppressWarnings("all") public void streamingPullExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockSubscriber.addException(exception); SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]"); int streamAckDeadlineSeconds = 1875467245; @@ -445,7 +456,7 @@ public void streamingPullExceptionTest() throws Exception { } catch (ExecutionException e) { Assert.assertTrue(e.getCause() instanceof StatusRuntimeException); StatusRuntimeException statusException = (StatusRuntimeException) e.getCause(); - Assert.assertEquals(Status.INTERNAL, statusException.getStatus()); + Assert.assertEquals(Status.INVALID_ARGUMENT, statusException.getStatus()); } } @@ -471,7 +482,7 @@ public void modifyPushConfigTest() { @Test @SuppressWarnings("all") public void modifyPushConfigExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockSubscriber.addException(exception); try { @@ -481,7 +492,124 @@ public void modifyPushConfigExceptionTest() throws Exception { client.modifyPushConfig(subscription, pushConfig); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); + } + } + + @Test + @SuppressWarnings("all") + public void listSnapshotsTest() { + String nextPageToken = ""; + Snapshot snapshotsElement = Snapshot.newBuilder().build(); + List snapshots = Arrays.asList(snapshotsElement); + ListSnapshotsResponse expectedResponse = + ListSnapshotsResponse.newBuilder() + .setNextPageToken(nextPageToken) + .addAllSnapshots(snapshots) + .build(); + mockSubscriber.addResponse(expectedResponse); + + ProjectName project = ProjectName.create("[PROJECT]"); + + ListSnapshotsPagedResponse pagedListResponse = client.listSnapshots(project); + + List resources = Lists.newArrayList(pagedListResponse.iterateAllElements()); + Assert.assertEquals(1, resources.size()); + Assert.assertEquals(expectedResponse.getSnapshotsList().get(0), resources.get(0)); + + List actualRequests = mockSubscriber.getRequests(); + Assert.assertEquals(1, actualRequests.size()); + ListSnapshotsRequest actualRequest = (ListSnapshotsRequest) actualRequests.get(0); + + Assert.assertEquals(project, actualRequest.getProjectAsProjectName()); + } + + @Test + @SuppressWarnings("all") + public void listSnapshotsExceptionTest() throws Exception { + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); + mockSubscriber.addException(exception); + + try { + ProjectName project = ProjectName.create("[PROJECT]"); + + client.listSnapshots(project); + Assert.fail("No exception raised"); + } catch (ApiException e) { + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); + } + } + + @Test + @SuppressWarnings("all") + public void createSnapshotTest() { + SnapshotName name2 = SnapshotName.create("[PROJECT]", "[SNAPSHOT]"); + TopicName topic = TopicName.create("[PROJECT]", "[TOPIC]"); + Snapshot expectedResponse = + Snapshot.newBuilder().setNameWithSnapshotName(name2).setTopicWithTopicName(topic).build(); + mockSubscriber.addResponse(expectedResponse); + + SnapshotName name = SnapshotName.create("[PROJECT]", "[SNAPSHOT]"); + SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]"); + + Snapshot actualResponse = client.createSnapshot(name, subscription); + Assert.assertEquals(expectedResponse, actualResponse); + + List actualRequests = mockSubscriber.getRequests(); + Assert.assertEquals(1, actualRequests.size()); + CreateSnapshotRequest actualRequest = (CreateSnapshotRequest) actualRequests.get(0); + + Assert.assertEquals(name, actualRequest.getNameAsSnapshotName()); + Assert.assertEquals(subscription, actualRequest.getSubscriptionAsSubscriptionName()); + } + + @Test + @SuppressWarnings("all") + public void createSnapshotExceptionTest() throws Exception { + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); + mockSubscriber.addException(exception); + + try { + SnapshotName name = SnapshotName.create("[PROJECT]", "[SNAPSHOT]"); + SubscriptionName subscription = SubscriptionName.create("[PROJECT]", "[SUBSCRIPTION]"); + + client.createSnapshot(name, subscription); + Assert.fail("No exception raised"); + } catch (ApiException e) { + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); + } + } + + @Test + @SuppressWarnings("all") + public void deleteSnapshotTest() { + Empty expectedResponse = Empty.newBuilder().build(); + mockSubscriber.addResponse(expectedResponse); + + SnapshotName snapshot = SnapshotName.create("[PROJECT]", "[SNAPSHOT]"); + + client.deleteSnapshot(snapshot); + + List actualRequests = mockSubscriber.getRequests(); + Assert.assertEquals(1, actualRequests.size()); + DeleteSnapshotRequest actualRequest = (DeleteSnapshotRequest) actualRequests.get(0); + + Assert.assertEquals(snapshot, actualRequest.getSnapshotAsSnapshotName()); + } + + @Test + @SuppressWarnings("all") + public void deleteSnapshotExceptionTest() throws Exception { + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); + mockSubscriber.addException(exception); + + try { + SnapshotName snapshot = SnapshotName.create("[PROJECT]", "[SNAPSHOT]"); + + client.deleteSnapshot(snapshot); + Assert.fail("No exception raised"); + } catch (ApiException e) { + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -510,7 +638,7 @@ public void setIamPolicyTest() { @Test @SuppressWarnings("all") public void setIamPolicyExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockIAMPolicy.addException(exception); try { @@ -520,7 +648,7 @@ public void setIamPolicyExceptionTest() throws Exception { client.setIamPolicy(formattedResource, policy); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -547,7 +675,7 @@ public void getIamPolicyTest() { @Test @SuppressWarnings("all") public void getIamPolicyExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockIAMPolicy.addException(exception); try { @@ -556,7 +684,7 @@ public void getIamPolicyExceptionTest() throws Exception { client.getIamPolicy(formattedResource); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -584,7 +712,7 @@ public void testIamPermissionsTest() { @Test @SuppressWarnings("all") public void testIamPermissionsExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockIAMPolicy.addException(exception); try { @@ -594,7 +722,7 @@ public void testIamPermissionsExceptionTest() throws Exception { client.testIamPermissions(formattedResource, permissions); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } } diff --git a/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/PublisherClientTest.java b/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/TopicAdminClientTest.java similarity index 93% rename from google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/PublisherClientTest.java rename to google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/TopicAdminClientTest.java index 39e39a817224..37bf7498f740 100644 --- a/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/PublisherClientTest.java +++ b/google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/TopicAdminClientTest.java @@ -57,12 +57,12 @@ import org.junit.Test; @javax.annotation.Generated("by GAPIC") -public class PublisherClientTest { +public class TopicAdminClientTest { private static MockPublisher mockPublisher; private static MockIAMPolicy mockIAMPolicy; private static MockSubscriber mockSubscriber; private static MockServiceHelper serviceHelper; - private PublisherClient client; + private TopicAdminClient client; @BeforeClass public static void startStaticServer() { @@ -84,11 +84,11 @@ public static void stopServer() { @Before public void setUp() throws IOException { serviceHelper.reset(); - PublisherSettings settings = - PublisherSettings.defaultBuilder() + TopicAdminSettings settings = + TopicAdminSettings.defaultBuilder() .setChannelProvider(serviceHelper.createChannelProvider()) .build(); - client = PublisherClient.create(settings); + client = TopicAdminClient.create(settings); } @After @@ -118,7 +118,7 @@ public void createTopicTest() { @Test @SuppressWarnings("all") public void createTopicExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockPublisher.addException(exception); try { @@ -127,7 +127,7 @@ public void createTopicExceptionTest() throws Exception { client.createTopic(name); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -159,7 +159,7 @@ public void publishTest() { @Test @SuppressWarnings("all") public void publishExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockPublisher.addException(exception); try { @@ -171,7 +171,7 @@ public void publishExceptionTest() throws Exception { client.publish(topic, messages); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -197,7 +197,7 @@ public void getTopicTest() { @Test @SuppressWarnings("all") public void getTopicExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockPublisher.addException(exception); try { @@ -206,7 +206,7 @@ public void getTopicExceptionTest() throws Exception { client.getTopic(topic); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -241,7 +241,7 @@ public void listTopicsTest() { @Test @SuppressWarnings("all") public void listTopicsExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockPublisher.addException(exception); try { @@ -250,7 +250,7 @@ public void listTopicsExceptionTest() throws Exception { client.listTopics(project); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -291,7 +291,7 @@ public void listTopicSubscriptionsTest() { @Test @SuppressWarnings("all") public void listTopicSubscriptionsExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockPublisher.addException(exception); try { @@ -300,7 +300,7 @@ public void listTopicSubscriptionsExceptionTest() throws Exception { client.listTopicSubscriptions(topic); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -324,7 +324,7 @@ public void deleteTopicTest() { @Test @SuppressWarnings("all") public void deleteTopicExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockPublisher.addException(exception); try { @@ -333,7 +333,7 @@ public void deleteTopicExceptionTest() throws Exception { client.deleteTopic(topic); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -362,7 +362,7 @@ public void setIamPolicyTest() { @Test @SuppressWarnings("all") public void setIamPolicyExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockIAMPolicy.addException(exception); try { @@ -372,7 +372,7 @@ public void setIamPolicyExceptionTest() throws Exception { client.setIamPolicy(formattedResource, policy); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -399,7 +399,7 @@ public void getIamPolicyTest() { @Test @SuppressWarnings("all") public void getIamPolicyExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockIAMPolicy.addException(exception); try { @@ -408,7 +408,7 @@ public void getIamPolicyExceptionTest() throws Exception { client.getIamPolicy(formattedResource); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -436,7 +436,7 @@ public void testIamPermissionsTest() { @Test @SuppressWarnings("all") public void testIamPermissionsExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockIAMPolicy.addException(exception); try { @@ -446,7 +446,7 @@ public void testIamPermissionsExceptionTest() throws Exception { client.testIamPermissions(formattedResource, permissions); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } } diff --git a/google-cloud-resourcemanager/README.md b/google-cloud-resourcemanager/README.md index b968d26b2a7f..07885556f2f9 100644 --- a/google-cloud-resourcemanager/README.md +++ b/google-cloud-resourcemanager/README.md @@ -22,16 +22,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-resourcemanager - 0.10.0-alpha + 0.12.0-alpha ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-resourcemanager:0.10.0-alpha' +compile 'com.google.cloud:google-cloud-resourcemanager:0.12.0-alpha' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-resourcemanager" % "0.10.0-alpha" +libraryDependencies += "com.google.cloud" % "google-cloud-resourcemanager" % "0.12.0-alpha" ``` Example Application diff --git a/google-cloud-resourcemanager/pom.xml b/google-cloud-resourcemanager/pom.xml index d20ceaa06dbc..16c884c73b73 100644 --- a/google-cloud-resourcemanager/pom.xml +++ b/google-cloud-resourcemanager/pom.xml @@ -11,7 +11,7 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-resourcemanager diff --git a/google-cloud-spanner/README.md b/google-cloud-spanner/README.md index b5e481b04657..6e1ee005957a 100644 --- a/google-cloud-spanner/README.md +++ b/google-cloud-spanner/README.md @@ -27,16 +27,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner - 0.10.0-beta + 0.12.0-beta ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner:0.10.0-beta' +compile 'com.google.cloud:google-cloud-spanner:0.12.0-beta' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "0.10.0-beta" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "0.12.0-beta" ``` ## Authentication diff --git a/google-cloud-spanner/pom.xml b/google-cloud-spanner/pom.xml index 31f62ba7bd45..d05c9020f9cb 100644 --- a/google-cloud-spanner/pom.xml +++ b/google-cloud-spanner/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-spanner @@ -152,16 +152,6 @@ joda-time 2.9.2 - - com.google.auth - google-auth-library-credentials - 0.4.0 - - - com.google.auth - google-auth-library-oauth2-http - 0.4.0 - com.google.api-client google-api-client diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java index a008bb602ffa..f051e351beab 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java @@ -43,7 +43,7 @@ public class SpannerOptions extends ServiceOptions { private static final String API_SHORT_NAME = "Spanner"; private static final String DEFAULT_HOST = "https://spanner.googleapis.com"; - private static final Set SCOPES = + private static final ImmutableSet SCOPES = ImmutableSet.of( "https://www.googleapis.com/auth/spanner.admin", "https://www.googleapis.com/auth/spanner.data"); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/GrpcResultSetTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/GrpcResultSetTest.java index b1dbdd15173c..e6e0e260516f 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/GrpcResultSetTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/GrpcResultSetTest.java @@ -462,6 +462,7 @@ public void profileResultInFinalResultSet() { resultSet.close(); } + @Test public void profileResultInExtraFinalResultSet() { Map statsMap = ImmutableMap.of( diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SessionPoolTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SessionPoolTest.java index 4744edd035d6..c4d910cba6ca 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SessionPoolTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SessionPoolTest.java @@ -32,6 +32,7 @@ import com.google.cloud.GrpcTransportOptions.ExecutorFactory; import com.google.cloud.spanner.SessionPool.Clock; import com.google.cloud.spanner.SessionPool.PooledSession; +import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.Uninterruptibles; import java.util.ArrayList; import java.util.Arrays; @@ -114,6 +115,123 @@ public void poolClosure() throws Exception { pool.closeAsync().get(); } + @Test + public void poolClosureFailsPendingReadWaiters() throws Exception { + final CountDownLatch insideCreation = new CountDownLatch(1); + final CountDownLatch releaseCreation = new CountDownLatch(1); + when(client.createSession(db)) + .thenReturn(mock(Session.class)) + .thenAnswer( + new Answer() { + @Override + public Session answer(InvocationOnMock invocation) throws Throwable { + insideCreation.countDown(); + releaseCreation.await(); + return mock(Session.class); + } + }); + pool = createPool(); + pool.getReadSession(); + AtomicBoolean failed = new AtomicBoolean(false); + CountDownLatch latch = new CountDownLatch(1); + getSessionAsync(latch, failed); + insideCreation.await(); + pool.closeAsync(); + releaseCreation.countDown(); + latch.await(); + assertThat(failed.get()).isTrue(); + } + + @Test + public void poolClosureFailsPendingWriteWaiters() throws Exception { + final CountDownLatch insideCreation = new CountDownLatch(1); + final CountDownLatch releaseCreation = new CountDownLatch(1); + when(client.createSession(db)) + .thenReturn(mock(Session.class)) + .thenAnswer( + new Answer() { + @Override + public Session answer(InvocationOnMock invocation) throws Throwable { + insideCreation.countDown(); + releaseCreation.await(); + return mock(Session.class); + } + }); + pool = createPool(); + pool.getReadSession(); + AtomicBoolean failed = new AtomicBoolean(false); + CountDownLatch latch = new CountDownLatch(1); + getReadWriteSessionAsync(latch, failed); + insideCreation.await(); + pool.closeAsync(); + releaseCreation.countDown(); + latch.await(); + assertThat(failed.get()).isTrue(); + } + + @Test + public void poolClosesEvenIfCreationFails() throws Exception { + final CountDownLatch insideCreation = new CountDownLatch(1); + final CountDownLatch releaseCreation = new CountDownLatch(1); + when(client.createSession(db)) + .thenAnswer( + new Answer() { + @Override + public Session answer(InvocationOnMock invocation) throws Throwable { + insideCreation.countDown(); + releaseCreation.await(); + throw SpannerExceptionFactory.newSpannerException(new RuntimeException()); + } + }); + pool = createPool(); + AtomicBoolean failed = new AtomicBoolean(false); + CountDownLatch latch = new CountDownLatch(1); + getSessionAsync(latch, failed); + insideCreation.await(); + ListenableFuture f = pool.closeAsync(); + releaseCreation.countDown(); + f.get(); + assertThat(f.isDone()).isTrue(); + } + + @Test + public void poolClosesEvenIfPreparationFails() throws Exception { + Session session = mock(Session.class); + when(client.createSession(db)).thenReturn(session); + final CountDownLatch insidePrepare = new CountDownLatch(1); + final CountDownLatch releasePrepare = new CountDownLatch(1); + doAnswer( + new Answer() { + @Override + public Session answer(InvocationOnMock invocation) throws Throwable { + insidePrepare.countDown(); + releasePrepare.await(); + throw SpannerExceptionFactory.newSpannerException(new RuntimeException()); + } + }) + .when(session) + .prepareReadWriteTransaction(); + pool = createPool(); + AtomicBoolean failed = new AtomicBoolean(false); + CountDownLatch latch = new CountDownLatch(1); + getReadWriteSessionAsync(latch, failed); + insidePrepare.await(); + ListenableFuture f = pool.closeAsync(); + releasePrepare.countDown(); + f.get(); + assertThat(f.isDone()).isTrue(); + } + + @Test + public void poolClosureFailsNewRequests() throws Exception { + when(client.createSession(db)).thenReturn(mock(Session.class)); + pool = createPool(); + pool.getReadSession(); + pool.closeAsync(); + expectedException.expect(IllegalStateException.class); + pool.getReadSession(); + } + @Test public void atMostMaxSessionsCreated() { AtomicBoolean failed = new AtomicBoolean(false); @@ -243,6 +361,35 @@ public Void answer(InvocationOnMock arg0) throws Throwable { writeSession.close(); } + @Test + public void getReadSessionFallsBackToWritePreparedSession() throws Exception { + Session mockSession1 = mock(Session.class); + final CountDownLatch prepareLatch = new CountDownLatch(2); + doAnswer( + new Answer() { + @Override + public Void answer(InvocationOnMock arg0) throws Throwable { + prepareLatch.countDown(); + return null; + } + }) + .when(mockSession1) + .prepareReadWriteTransaction(); + when(client.createSession(db)).thenReturn(mockSession1); + options = + SessionPoolOptions.newBuilder() + .setMinSessions(minSessions) + .setMaxSessions(1) + .setWriteSessionsFraction(1.0f) + .build(); + pool = createPool(); + pool.getReadWriteSession().close(); + prepareLatch.await(); + // This session should also be write prepared. + PooledSession readSession = (PooledSession) pool.getReadSession(); + verify(readSession.delegate, times(2)).prepareReadWriteTransaction(); + } + @Test public void failOnPoolExhaustion() { options = @@ -262,6 +409,18 @@ public void failOnPoolExhaustion() { session1.close(); } + @Test + public void poolWorksWhenSessionNotFound() { + Session mockSession1 = mock(Session.class); + Session mockSession2 = mock(Session.class); + doThrow(SpannerExceptionFactory.newSpannerException(ErrorCode.NOT_FOUND, "Session not found")) + .when(mockSession1) + .prepareReadWriteTransaction(); + when(client.createSession(db)).thenReturn(mockSession1).thenReturn(mockSession2); + pool = createPool(); + assertThat(((PooledSession) pool.getReadWriteSession()).delegate).isEqualTo(mockSession2); + } + @Test public void idleSessionCleanup() throws Exception { options = @@ -366,6 +525,9 @@ public void run() { try (Session session = pool.getReadSession()) { failed.compareAndSet(false, session == null); Uninterruptibles.sleepUninterruptibly(10, TimeUnit.MILLISECONDS); + } catch (SpannerException e) { + failed.compareAndSet(false, true); + } finally { latch.countDown(); } } @@ -381,6 +543,9 @@ public void run() { try (Session session = pool.getReadWriteSession()) { failed.compareAndSet(false, session == null); Uninterruptibles.sleepUninterruptibly(2, TimeUnit.MILLISECONDS); + } catch (SpannerException e) { + failed.compareAndSet(false, true); + } finally { latch.countDown(); } } diff --git a/google-cloud-speech/pom.xml b/google-cloud-speech/pom.xml index 2e94ebacac24..071e68a12da3 100644 --- a/google-cloud-speech/pom.xml +++ b/google-cloud-speech/pom.xml @@ -11,10 +11,11 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-speech + ${project.version} @@ -38,6 +39,17 @@ + + com.google.api.grpc + grpc-google-cloud-speech-v1 + 0.1.6 + + + io.grpc + grpc-all + + + io.grpc grpc-netty @@ -87,6 +99,22 @@ + + org.codehaus.mojo + properties-maven-plugin + 1.0-alpha-2 + + + generate-resources + + write-project-properties + + + ${project.build.outputDirectory}/project.properties + + + + org.codehaus.mojo build-helper-maven-plugin diff --git a/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1/SpeechClient.java b/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1/SpeechClient.java new file mode 100644 index 000000000000..f2ad4901caae --- /dev/null +++ b/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1/SpeechClient.java @@ -0,0 +1,515 @@ +/* + * Copyright 2017, Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.speech.spi.v1; + +import com.google.api.gax.grpc.ChannelAndExecutor; +import com.google.api.gax.grpc.FixedChannelProvider; +import com.google.api.gax.grpc.FixedExecutorProvider; +import com.google.api.gax.grpc.OperationCallable; +import com.google.api.gax.grpc.OperationFuture; +import com.google.api.gax.grpc.StreamingCallable; +import com.google.api.gax.grpc.UnaryCallable; +import com.google.cloud.speech.v1.LongRunningRecognizeRequest; +import com.google.cloud.speech.v1.LongRunningRecognizeResponse; +import com.google.cloud.speech.v1.RecognitionAudio; +import com.google.cloud.speech.v1.RecognitionConfig; +import com.google.cloud.speech.v1.RecognizeRequest; +import com.google.cloud.speech.v1.RecognizeResponse; +import com.google.cloud.speech.v1.StreamingRecognizeRequest; +import com.google.cloud.speech.v1.StreamingRecognizeResponse; +import com.google.longrunning.Operation; +import com.google.longrunning.OperationsClient; +import com.google.longrunning.OperationsSettings; +import com.google.protobuf.ExperimentalApi; +import io.grpc.ManagedChannel; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import javax.annotation.Generated; + +// AUTO-GENERATED DOCUMENTATION AND SERVICE +/** + * Service Description: Service that implements Google Cloud Speech API. + * + *

    This class provides the ability to make remote calls to the backing service through method + * calls that map to API methods. Sample code to get started: + * + *

    + * 
    + * try (SpeechClient speechClient = SpeechClient.create()) {
    + *   RecognitionConfig.AudioEncoding encoding = RecognitionConfig.AudioEncoding.FLAC;
    + *   int sampleRateHertz = 44100;
    + *   String languageCode = "en-US";
    + *   RecognitionConfig config = RecognitionConfig.newBuilder()
    + *     .setEncoding(encoding)
    + *     .setSampleRateHertz(sampleRateHertz)
    + *     .setLanguageCode(languageCode)
    + *     .build();
    + *   String uri = "gs://bucket_name/file_name.flac";
    + *   RecognitionAudio audio = RecognitionAudio.newBuilder()
    + *     .setUri(uri)
    + *     .build();
    + *   RecognizeResponse response = speechClient.recognize(config, audio);
    + * }
    + * 
    + * 
    + * + *

    Note: close() needs to be called on the speechClient object to clean up resources such as + * threads. In the example above, try-with-resources is used, which automatically calls close(). + * + *

    The surface of this class includes several types of Java methods for each of the API's + * methods: + * + *

      + *
    1. A "flattened" method. With this type of method, the fields of the request type have been + * converted into function parameters. It may be the case that not all fields are available as + * parameters, and not every API method will have a flattened method entry point. + *
    2. A "request object" method. This type of method only takes one parameter, a request object, + * which must be constructed before the call. Not every API method will have a request object + * method. + *
    3. A "callable" method. This type of method takes no parameters and returns an immutable API + * callable object, which can be used to initiate calls to the service. + *
    + * + *

    See the individual methods for example code. + * + *

    Many parameters require resource names to be formatted in a particular way. To assist with + * these names, this class includes a format method for each type of name, and additionally a parse + * method to extract the individual identifiers contained within names that are returned. + * + *

    This class can be customized by passing in a custom instance of SpeechSettings to create(). + * For example: + * + *

    + * 
    + * InstantiatingChannelProvider channelProvider =
    + *     SpeechSettings.defaultChannelProviderBuilder()
    + *         .setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
    + *         .build();
    + * SpeechSettings speechSettings =
    + *     SpeechSettings.defaultBuilder().setChannelProvider(channelProvider).build();
    + * SpeechClient speechClient =
    + *     SpeechClient.create(speechSettings);
    + * 
    + * 
    + */ +@Generated("by GAPIC") +@ExperimentalApi +public class SpeechClient implements AutoCloseable { + private final SpeechSettings settings; + private final ScheduledExecutorService executor; + private final ManagedChannel channel; + private final OperationsClient operationsClient; + private final List closeables = new ArrayList<>(); + + private final UnaryCallable recognizeCallable; + private final UnaryCallable longRunningRecognizeCallable; + private final OperationCallable + longRunningRecognizeOperationCallable; + private final StreamingCallable + streamingRecognizeCallable; + + /** Constructs an instance of SpeechClient with default settings. */ + public static final SpeechClient create() throws IOException { + return create(SpeechSettings.defaultBuilder().build()); + } + + /** + * Constructs an instance of SpeechClient, using the given settings. The channels are created + * based on the settings passed in, or defaults for any settings that are not set. + */ + public static final SpeechClient create(SpeechSettings settings) throws IOException { + return new SpeechClient(settings); + } + + /** + * Constructs an instance of SpeechClient, using the given settings. This is protected so that it + * easy to make a subclass, but otherwise, the static factory methods should be preferred. + */ + protected SpeechClient(SpeechSettings settings) throws IOException { + this.settings = settings; + ChannelAndExecutor channelAndExecutor = settings.getChannelAndExecutor(); + this.executor = channelAndExecutor.getExecutor(); + this.channel = channelAndExecutor.getChannel(); + + FixedExecutorProvider executorProvider = FixedExecutorProvider.create(this.executor); + FixedChannelProvider channelProvider = FixedChannelProvider.create(this.channel); + OperationsSettings operationsSettings = + OperationsSettings.defaultBuilder() + .setExecutorProvider(executorProvider) + .setChannelProvider(channelProvider) + .build(); + this.operationsClient = OperationsClient.create(operationsSettings); + + this.recognizeCallable = + UnaryCallable.create(settings.recognizeSettings(), this.channel, this.executor); + this.longRunningRecognizeCallable = + UnaryCallable.create( + settings.longRunningRecognizeSettings().getInitialCallSettings(), + this.channel, + this.executor); + this.longRunningRecognizeOperationCallable = + OperationCallable.create( + settings.longRunningRecognizeSettings(), + this.channel, + this.executor, + this.operationsClient); + this.streamingRecognizeCallable = + StreamingCallable.create(settings.streamingRecognizeSettings(), this.channel); + + if (settings.getChannelProvider().shouldAutoClose()) { + closeables.add( + new Closeable() { + @Override + public void close() throws IOException { + channel.shutdown(); + } + }); + } + if (settings.getExecutorProvider().shouldAutoClose()) { + closeables.add( + new Closeable() { + @Override + public void close() throws IOException { + executor.shutdown(); + } + }); + } + } + + public final SpeechSettings getSettings() { + return settings; + } + + /** + * Returns the OperationsClient that can be used to query the status of a long-running operation + * returned by another API method call. + */ + public final OperationsClient getOperationsClient() { + return operationsClient; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Performs synchronous speech recognition: receive results after all audio has been sent and + * processed. + * + *

    Sample code: + * + *

    
    +   * try (SpeechClient speechClient = SpeechClient.create()) {
    +   *   RecognitionConfig.AudioEncoding encoding = RecognitionConfig.AudioEncoding.FLAC;
    +   *   int sampleRateHertz = 44100;
    +   *   String languageCode = "en-US";
    +   *   RecognitionConfig config = RecognitionConfig.newBuilder()
    +   *     .setEncoding(encoding)
    +   *     .setSampleRateHertz(sampleRateHertz)
    +   *     .setLanguageCode(languageCode)
    +   *     .build();
    +   *   String uri = "gs://bucket_name/file_name.flac";
    +   *   RecognitionAudio audio = RecognitionAudio.newBuilder()
    +   *     .setUri(uri)
    +   *     .build();
    +   *   RecognizeResponse response = speechClient.recognize(config, audio);
    +   * }
    +   * 
    + * + * @param config *Required* Provides information to the recognizer that specifies how to + * process the request. + * @param audio *Required* The audio data to be recognized. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final RecognizeResponse recognize(RecognitionConfig config, RecognitionAudio audio) { + + RecognizeRequest request = + RecognizeRequest.newBuilder().setConfig(config).setAudio(audio).build(); + return recognize(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Performs synchronous speech recognition: receive results after all audio has been sent and + * processed. + * + *

    Sample code: + * + *

    
    +   * try (SpeechClient speechClient = SpeechClient.create()) {
    +   *   RecognitionConfig.AudioEncoding encoding = RecognitionConfig.AudioEncoding.FLAC;
    +   *   int sampleRateHertz = 44100;
    +   *   String languageCode = "en-US";
    +   *   RecognitionConfig config = RecognitionConfig.newBuilder()
    +   *     .setEncoding(encoding)
    +   *     .setSampleRateHertz(sampleRateHertz)
    +   *     .setLanguageCode(languageCode)
    +   *     .build();
    +   *   String uri = "gs://bucket_name/file_name.flac";
    +   *   RecognitionAudio audio = RecognitionAudio.newBuilder()
    +   *     .setUri(uri)
    +   *     .build();
    +   *   RecognizeRequest request = RecognizeRequest.newBuilder()
    +   *     .setConfig(config)
    +   *     .setAudio(audio)
    +   *     .build();
    +   *   RecognizeResponse response = speechClient.recognize(request);
    +   * }
    +   * 
    + * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final RecognizeResponse recognize(RecognizeRequest request) { + return recognizeCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Performs synchronous speech recognition: receive results after all audio has been sent and + * processed. + * + *

    Sample code: + * + *

    
    +   * try (SpeechClient speechClient = SpeechClient.create()) {
    +   *   RecognitionConfig.AudioEncoding encoding = RecognitionConfig.AudioEncoding.FLAC;
    +   *   int sampleRateHertz = 44100;
    +   *   String languageCode = "en-US";
    +   *   RecognitionConfig config = RecognitionConfig.newBuilder()
    +   *     .setEncoding(encoding)
    +   *     .setSampleRateHertz(sampleRateHertz)
    +   *     .setLanguageCode(languageCode)
    +   *     .build();
    +   *   String uri = "gs://bucket_name/file_name.flac";
    +   *   RecognitionAudio audio = RecognitionAudio.newBuilder()
    +   *     .setUri(uri)
    +   *     .build();
    +   *   RecognizeRequest request = RecognizeRequest.newBuilder()
    +   *     .setConfig(config)
    +   *     .setAudio(audio)
    +   *     .build();
    +   *   ApiFuture<RecognizeResponse> future = speechClient.recognizeCallable().futureCall(request);
    +   *   // Do something
    +   *   RecognizeResponse response = future.get();
    +   * }
    +   * 
    + */ + public final UnaryCallable recognizeCallable() { + return recognizeCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Performs asynchronous speech recognition: receive results via the google.longrunning.Operations + * interface. Returns either an `Operation.error` or an `Operation.response` which contains a + * `LongRunningRecognizeResponse` message. + * + *

    Sample code: + * + *

    
    +   * try (SpeechClient speechClient = SpeechClient.create()) {
    +   *   RecognitionConfig.AudioEncoding encoding = RecognitionConfig.AudioEncoding.FLAC;
    +   *   int sampleRateHertz = 44100;
    +   *   String languageCode = "en-US";
    +   *   RecognitionConfig config = RecognitionConfig.newBuilder()
    +   *     .setEncoding(encoding)
    +   *     .setSampleRateHertz(sampleRateHertz)
    +   *     .setLanguageCode(languageCode)
    +   *     .build();
    +   *   String uri = "gs://bucket_name/file_name.flac";
    +   *   RecognitionAudio audio = RecognitionAudio.newBuilder()
    +   *     .setUri(uri)
    +   *     .build();
    +   *   LongRunningRecognizeResponse response = speechClient.longRunningRecognizeAsync(config, audio).get();
    +   * }
    +   * 
    + * + * @param config *Required* Provides information to the recognizer that specifies how to + * process the request. + * @param audio *Required* The audio data to be recognized. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final OperationFuture longRunningRecognizeAsync( + RecognitionConfig config, RecognitionAudio audio) { + + LongRunningRecognizeRequest request = + LongRunningRecognizeRequest.newBuilder().setConfig(config).setAudio(audio).build(); + return longRunningRecognizeAsync(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Performs asynchronous speech recognition: receive results via the google.longrunning.Operations + * interface. Returns either an `Operation.error` or an `Operation.response` which contains a + * `LongRunningRecognizeResponse` message. + * + *

    Sample code: + * + *

    
    +   * try (SpeechClient speechClient = SpeechClient.create()) {
    +   *   RecognitionConfig.AudioEncoding encoding = RecognitionConfig.AudioEncoding.FLAC;
    +   *   int sampleRateHertz = 44100;
    +   *   String languageCode = "en-US";
    +   *   RecognitionConfig config = RecognitionConfig.newBuilder()
    +   *     .setEncoding(encoding)
    +   *     .setSampleRateHertz(sampleRateHertz)
    +   *     .setLanguageCode(languageCode)
    +   *     .build();
    +   *   String uri = "gs://bucket_name/file_name.flac";
    +   *   RecognitionAudio audio = RecognitionAudio.newBuilder()
    +   *     .setUri(uri)
    +   *     .build();
    +   *   LongRunningRecognizeRequest request = LongRunningRecognizeRequest.newBuilder()
    +   *     .setConfig(config)
    +   *     .setAudio(audio)
    +   *     .build();
    +   *   LongRunningRecognizeResponse response = speechClient.longRunningRecognizeAsync(request).get();
    +   * }
    +   * 
    + * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final OperationFuture longRunningRecognizeAsync( + LongRunningRecognizeRequest request) { + return longRunningRecognizeOperationCallable().futureCall(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Performs asynchronous speech recognition: receive results via the google.longrunning.Operations + * interface. Returns either an `Operation.error` or an `Operation.response` which contains a + * `LongRunningRecognizeResponse` message. + * + *

    Sample code: + * + *

    
    +   * try (SpeechClient speechClient = SpeechClient.create()) {
    +   *   RecognitionConfig.AudioEncoding encoding = RecognitionConfig.AudioEncoding.FLAC;
    +   *   int sampleRateHertz = 44100;
    +   *   String languageCode = "en-US";
    +   *   RecognitionConfig config = RecognitionConfig.newBuilder()
    +   *     .setEncoding(encoding)
    +   *     .setSampleRateHertz(sampleRateHertz)
    +   *     .setLanguageCode(languageCode)
    +   *     .build();
    +   *   String uri = "gs://bucket_name/file_name.flac";
    +   *   RecognitionAudio audio = RecognitionAudio.newBuilder()
    +   *     .setUri(uri)
    +   *     .build();
    +   *   LongRunningRecognizeRequest request = LongRunningRecognizeRequest.newBuilder()
    +   *     .setConfig(config)
    +   *     .setAudio(audio)
    +   *     .build();
    +   *   OperationFuture<Operation> future = speechClient.longRunningRecognizeOperationCallable().futureCall(request);
    +   *   // Do something
    +   *   LongRunningRecognizeResponse response = future.get();
    +   * }
    +   * 
    + */ + public final OperationCallable + longRunningRecognizeOperationCallable() { + return longRunningRecognizeOperationCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Performs asynchronous speech recognition: receive results via the google.longrunning.Operations + * interface. Returns either an `Operation.error` or an `Operation.response` which contains a + * `LongRunningRecognizeResponse` message. + * + *

    Sample code: + * + *

    
    +   * try (SpeechClient speechClient = SpeechClient.create()) {
    +   *   RecognitionConfig.AudioEncoding encoding = RecognitionConfig.AudioEncoding.FLAC;
    +   *   int sampleRateHertz = 44100;
    +   *   String languageCode = "en-US";
    +   *   RecognitionConfig config = RecognitionConfig.newBuilder()
    +   *     .setEncoding(encoding)
    +   *     .setSampleRateHertz(sampleRateHertz)
    +   *     .setLanguageCode(languageCode)
    +   *     .build();
    +   *   String uri = "gs://bucket_name/file_name.flac";
    +   *   RecognitionAudio audio = RecognitionAudio.newBuilder()
    +   *     .setUri(uri)
    +   *     .build();
    +   *   LongRunningRecognizeRequest request = LongRunningRecognizeRequest.newBuilder()
    +   *     .setConfig(config)
    +   *     .setAudio(audio)
    +   *     .build();
    +   *   ApiFuture<Operation> future = speechClient.longRunningRecognizeCallable().futureCall(request);
    +   *   // Do something
    +   *   Operation response = future.get();
    +   * }
    +   * 
    + */ + public final UnaryCallable + longRunningRecognizeCallable() { + return longRunningRecognizeCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Performs bidirectional streaming speech recognition: receive results while sending audio. This + * method is only available via the gRPC API (not REST). + * + *

    Sample code: + * + *

    
    +   * try (SpeechClient speechClient = SpeechClient.create()) {
    +   *   ApiStreamObserver<StreamingRecognizeResponse> responseObserver =
    +   *       new ApiStreamObserver<StreamingRecognizeResponse>() {
    +   *         {@literal @}Override
    +   *         public void onNext(StreamingRecognizeResponse response) {
    +   *           // Do something when receive a response
    +   *         }
    +   *
    +   *         {@literal @}Override
    +   *         public void onError(Throwable t) {
    +   *           // Add error-handling
    +   *         }
    +   *
    +   *         {@literal @}Override
    +   *         public void onCompleted() {
    +   *           // Do something when complete.
    +   *         }
    +   *       };
    +   *   ApiStreamObserver<StreamingRecognizeRequest> requestObserver =
    +   *       speechClient.streamingRecognizeCallable().bidiStreamingCall(responseObserver)});
    +   *
    +   *   StreamingRecognizeRequest request = StreamingRecognizeRequest.newBuilder().build();
    +   *   requestObserver.onNext(request);
    +   * }
    +   * 
    + */ + public final StreamingCallable + streamingRecognizeCallable() { + return streamingRecognizeCallable; + } + + /** + * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately + * cancelled. + */ + @Override + public final void close() throws Exception { + for (AutoCloseable closeable : closeables) { + closeable.close(); + } + } +} diff --git a/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1/SpeechSettings.java b/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1/SpeechSettings.java new file mode 100644 index 000000000000..db87fa0500b7 --- /dev/null +++ b/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1/SpeechSettings.java @@ -0,0 +1,305 @@ +/* + * Copyright 2017, Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.speech.spi.v1; + +import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; +import com.google.api.gax.core.RetrySettings; +import com.google.api.gax.grpc.ChannelProvider; +import com.google.api.gax.grpc.ClientSettings; +import com.google.api.gax.grpc.ExecutorProvider; +import com.google.api.gax.grpc.InstantiatingChannelProvider; +import com.google.api.gax.grpc.InstantiatingExecutorProvider; +import com.google.api.gax.grpc.OperationCallSettings; +import com.google.api.gax.grpc.SimpleCallSettings; +import com.google.api.gax.grpc.StreamingCallSettings; +import com.google.api.gax.grpc.UnaryCallSettings; +import com.google.cloud.speech.v1.LongRunningRecognizeRequest; +import com.google.cloud.speech.v1.LongRunningRecognizeResponse; +import com.google.cloud.speech.v1.RecognizeRequest; +import com.google.cloud.speech.v1.RecognizeResponse; +import com.google.cloud.speech.v1.SpeechGrpc; +import com.google.cloud.speech.v1.StreamingRecognizeRequest; +import com.google.cloud.speech.v1.StreamingRecognizeResponse; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.google.protobuf.ExperimentalApi; +import io.grpc.Status; +import java.io.IOException; +import javax.annotation.Generated; +import org.joda.time.Duration; + +// AUTO-GENERATED DOCUMENTATION AND CLASS +/** + * Settings class to configure an instance of {@link SpeechClient}. + * + *

    The default instance has everything set to sensible defaults: + * + *

      + *
    • The default service address (speech.googleapis.com) and default port (443) are used. + *
    • Credentials are acquired automatically through Application Default Credentials. + *
    • Retries are configured for idempotent methods but not for non-idempotent methods. + *
    + * + *

    The builder of this class is recursive, so contained classes are themselves builders. When + * build() is called, the tree of builders is called to create the complete settings object. For + * example, to set the total timeout of recognize to 30 seconds: + * + *

    + * 
    + * SpeechSettings.Builder speechSettingsBuilder =
    + *     SpeechSettings.defaultBuilder();
    + * speechSettingsBuilder.recognizeSettings().getRetrySettingsBuilder()
    + *     .setTotalTimeout(Duration.standardSeconds(30));
    + * SpeechSettings speechSettings = speechSettingsBuilder.build();
    + * 
    + * 
    + */ +@Generated("by GAPIC v0.0.5") +@ExperimentalApi +public class SpeechSettings extends ClientSettings { + /** The default scopes of the service. */ + private static final ImmutableList DEFAULT_SERVICE_SCOPES = + ImmutableList.builder().add("https://www.googleapis.com/auth/cloud-platform").build(); + + private static final String DEFAULT_GAPIC_NAME = "gapic"; + private static final String DEFAULT_GAPIC_VERSION = ""; + + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + + private final SimpleCallSettings recognizeSettings; + private final OperationCallSettings + longRunningRecognizeSettings; + private final StreamingCallSettings + streamingRecognizeSettings; + + /** Returns the object with the settings used for calls to recognize. */ + public SimpleCallSettings recognizeSettings() { + return recognizeSettings; + } + + /** Returns the object with the settings used for calls to longRunningRecognize. */ + public OperationCallSettings + longRunningRecognizeSettings() { + return longRunningRecognizeSettings; + } + + /** Returns the object with the settings used for calls to streamingRecognize. */ + public StreamingCallSettings + streamingRecognizeSettings() { + return streamingRecognizeSettings; + } + + /** Returns a builder for the default ExecutorProvider for this service. */ + public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() { + return InstantiatingExecutorProvider.newBuilder(); + } + + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "speech.googleapis.com:443"; + } + + /** Returns the default service scopes. */ + public static ImmutableList getDefaultServiceScopes() { + return DEFAULT_SERVICE_SCOPES; + } + + /** Returns a builder for the default credentials for this service. */ + public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilder() { + return GoogleCredentialsProvider.newBuilder().setScopesToApply(DEFAULT_SERVICE_SCOPES); + } + + /** Returns a builder for the default ChannelProvider for this service. */ + public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { + return InstantiatingChannelProvider.newBuilder() + .setEndpoint(getDefaultEndpoint()) + .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) + .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); + } + + private static String getGapicVersion() { + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty(SpeechSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; + } + + /** Returns a builder for this class with recommended defaults. */ + public static Builder defaultBuilder() { + return Builder.createDefault(); + } + + /** Returns a new builder for this class. */ + public static Builder newBuilder() { + return new Builder(); + } + + /** Returns a builder containing all the values of this settings class. */ + public Builder toBuilder() { + return new Builder(this); + } + + private SpeechSettings(Builder settingsBuilder) throws IOException { + super(settingsBuilder.getExecutorProvider(), settingsBuilder.getChannelProvider()); + + recognizeSettings = settingsBuilder.recognizeSettings().build(); + longRunningRecognizeSettings = settingsBuilder.longRunningRecognizeSettings().build(); + streamingRecognizeSettings = settingsBuilder.streamingRecognizeSettings().build(); + } + + /** Builder for SpeechSettings. */ + public static class Builder extends ClientSettings.Builder { + private final ImmutableList unaryMethodSettingsBuilders; + + private final SimpleCallSettings.Builder recognizeSettings; + private final OperationCallSettings.Builder< + LongRunningRecognizeRequest, LongRunningRecognizeResponse> + longRunningRecognizeSettings; + private final StreamingCallSettings.Builder< + StreamingRecognizeRequest, StreamingRecognizeResponse> + streamingRecognizeSettings; + + private static final ImmutableMap> RETRYABLE_CODE_DEFINITIONS; + + static { + ImmutableMap.Builder> definitions = ImmutableMap.builder(); + definitions.put( + "idempotent", + Sets.immutableEnumSet( + Lists.newArrayList( + Status.Code.DEADLINE_EXCEEDED, Status.Code.UNAVAILABLE))); + definitions.put( + "non_idempotent", + Sets.immutableEnumSet(Lists.newArrayList(Status.Code.UNAVAILABLE))); + RETRYABLE_CODE_DEFINITIONS = definitions.build(); + } + + private static final ImmutableMap RETRY_PARAM_DEFINITIONS; + + static { + ImmutableMap.Builder definitions = ImmutableMap.builder(); + RetrySettings.Builder settingsBuilder = null; + settingsBuilder = + RetrySettings.newBuilder() + .setInitialRetryDelay(Duration.millis(100L)) + .setRetryDelayMultiplier(1.3) + .setMaxRetryDelay(Duration.millis(60000L)) + .setInitialRpcTimeout(Duration.millis(190000L)) + .setRpcTimeoutMultiplier(1.0) + .setMaxRpcTimeout(Duration.millis(190000L)) + .setTotalTimeout(Duration.millis(600000L)); + definitions.put("default", settingsBuilder); + RETRY_PARAM_DEFINITIONS = definitions.build(); + } + + private Builder() { + super(defaultChannelProviderBuilder().build()); + + recognizeSettings = SimpleCallSettings.newBuilder(SpeechGrpc.METHOD_RECOGNIZE); + + longRunningRecognizeSettings = + OperationCallSettings.newBuilder( + SpeechGrpc.METHOD_LONG_RUNNING_RECOGNIZE, LongRunningRecognizeResponse.class); + longRunningRecognizeSettings.setPollingInterval(Duration.millis(60000)); + + streamingRecognizeSettings = + StreamingCallSettings.newBuilder(SpeechGrpc.METHOD_STREAMING_RECOGNIZE); + + unaryMethodSettingsBuilders = ImmutableList.of(recognizeSettings); + } + + private static Builder createDefault() { + Builder builder = new Builder(); + + builder + .recognizeSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + builder + .longRunningRecognizeSettings() + .getInitialCallSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + return builder; + } + + private Builder(SpeechSettings settings) { + super(settings); + + recognizeSettings = settings.recognizeSettings.toBuilder(); + longRunningRecognizeSettings = settings.longRunningRecognizeSettings.toBuilder(); + streamingRecognizeSettings = settings.streamingRecognizeSettings.toBuilder(); + + unaryMethodSettingsBuilders = ImmutableList.of(recognizeSettings); + } + + @Override + public Builder setExecutorProvider(ExecutorProvider executorProvider) { + super.setExecutorProvider(executorProvider); + return this; + } + + @Override + public Builder setChannelProvider(ChannelProvider channelProvider) { + super.setChannelProvider(channelProvider); + return this; + } + + /** + * Applies the given settings to all of the unary API methods in this service. Only values that + * are non-null will be applied, so this method is not capable of un-setting any values. + * + *

    Note: This method does not support applying settings to streaming methods. + */ + public Builder applyToAllUnaryMethods(UnaryCallSettings.Builder unaryCallSettings) + throws Exception { + super.applyToAllUnaryMethods(unaryMethodSettingsBuilders, unaryCallSettings); + return this; + } + + /** Returns the builder for the settings used for calls to recognize. */ + public SimpleCallSettings.Builder recognizeSettings() { + return recognizeSettings; + } + + /** Returns the builder for the settings used for calls to longRunningRecognize. */ + public OperationCallSettings.Builder + longRunningRecognizeSettings() { + return longRunningRecognizeSettings; + } + + /** Returns the builder for the settings used for calls to streamingRecognize. */ + public StreamingCallSettings.Builder + streamingRecognizeSettings() { + return streamingRecognizeSettings; + } + + @Override + public SpeechSettings build() throws IOException { + return new SpeechSettings(this); + } + } +} diff --git a/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1/package-info.java b/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1/package-info.java new file mode 100644 index 000000000000..058cb76d82c8 --- /dev/null +++ b/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1/package-info.java @@ -0,0 +1,48 @@ +/* + * Copyright 2017, Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * A client to Google Cloud Speech API. + * + *

    The interfaces provided are listed below, along with usage samples. + * + *

    ============ SpeechClient ============ + * + *

    Service Description: Service that implements Google Cloud Speech API. + * + *

    Sample for SpeechClient: + * + *

    + * 
    + * try (SpeechClient speechClient = SpeechClient.create()) {
    + *   RecognitionConfig.AudioEncoding encoding = RecognitionConfig.AudioEncoding.FLAC;
    + *   int sampleRateHertz = 44100;
    + *   String languageCode = "en-US";
    + *   RecognitionConfig config = RecognitionConfig.newBuilder()
    + *     .setEncoding(encoding)
    + *     .setSampleRateHertz(sampleRateHertz)
    + *     .setLanguageCode(languageCode)
    + *     .build();
    + *   String uri = "gs://bucket_name/file_name.flac";
    + *   RecognitionAudio audio = RecognitionAudio.newBuilder()
    + *     .setUri(uri)
    + *     .build();
    + *   RecognizeResponse response = speechClient.recognize(config, audio);
    + * }
    + * 
    + * 
    + */ +package com.google.cloud.speech.spi.v1; diff --git a/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1beta1/SpeechClient.java b/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1beta1/SpeechClient.java index 6da697beaccb..34618c5af1f6 100644 --- a/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1beta1/SpeechClient.java +++ b/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1beta1/SpeechClient.java @@ -201,7 +201,7 @@ public final OperationsClient getOperationsClient() { // AUTO-GENERATED DOCUMENTATION AND METHOD /** - * Perform synchronous speech-recognition: receive results after all audio has been sent and + * Performs synchronous speech recognition: receive results after all audio has been sent and * processed. * *

    Sample code: @@ -222,9 +222,9 @@ public final OperationsClient getOperationsClient() { * } *

    * - * @param config [Required] The `config` message provides information to the recognizer that - * specifies how to process the request. - * @param audio [Required] The audio data to be recognized. + * @param config *Required* Provides information to the recognizer that specifies how to + * process the request. + * @param audio *Required* The audio data to be recognized. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ public final SyncRecognizeResponse syncRecognize( @@ -237,7 +237,7 @@ public final SyncRecognizeResponse syncRecognize( // AUTO-GENERATED DOCUMENTATION AND METHOD /** - * Perform synchronous speech-recognition: receive results after all audio has been sent and + * Performs synchronous speech recognition: receive results after all audio has been sent and * processed. * *

    Sample code: @@ -271,7 +271,7 @@ public final SyncRecognizeResponse syncRecognize(SyncRecognizeRequest request) { // AUTO-GENERATED DOCUMENTATION AND METHOD /** - * Perform synchronous speech-recognition: receive results after all audio has been sent and + * Performs synchronous speech recognition: receive results after all audio has been sent and * processed. * *

    Sample code: @@ -304,7 +304,8 @@ public final UnaryCallable syncReco // AUTO-GENERATED DOCUMENTATION AND METHOD /** - * Perform asynchronous speech-recognition: receive results via the google.longrunning.Operations + * Performs asynchronous speech recognition: receive results via the + * [google.longrunning.Operations] (/speech/reference/rest/v1beta1/operations#Operation) * interface. Returns either an `Operation.error` or an `Operation.response` which contains an * `AsyncRecognizeResponse` message. * @@ -326,9 +327,9 @@ public final UnaryCallable syncReco * } *

    * - * @param config [Required] The `config` message provides information to the recognizer that - * specifies how to process the request. - * @param audio [Required] The audio data to be recognized. + * @param config *Required* Provides information to the recognizer that specifies how to + * process the request. + * @param audio *Required* The audio data to be recognized. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ public final OperationFuture asyncRecognizeAsync( @@ -341,7 +342,8 @@ public final OperationFuture asyncRecognizeAsync( // AUTO-GENERATED DOCUMENTATION AND METHOD /** - * Perform asynchronous speech-recognition: receive results via the google.longrunning.Operations + * Performs asynchronous speech recognition: receive results via the + * [google.longrunning.Operations] (/speech/reference/rest/v1beta1/operations#Operation) * interface. Returns either an `Operation.error` or an `Operation.response` which contains an * `AsyncRecognizeResponse` message. * @@ -377,7 +379,8 @@ public final OperationFuture asyncRecognizeAsync( // AUTO-GENERATED DOCUMENTATION AND METHOD /** - * Perform asynchronous speech-recognition: receive results via the google.longrunning.Operations + * Performs asynchronous speech recognition: receive results via the + * [google.longrunning.Operations] (/speech/reference/rest/v1beta1/operations#Operation) * interface. Returns either an `Operation.error` or an `Operation.response` which contains an * `AsyncRecognizeResponse` message. * @@ -412,7 +415,8 @@ public final OperationFuture asyncRecognizeAsync( // AUTO-GENERATED DOCUMENTATION AND METHOD /** - * Perform asynchronous speech-recognition: receive results via the google.longrunning.Operations + * Performs asynchronous speech recognition: receive results via the + * [google.longrunning.Operations] (/speech/reference/rest/v1beta1/operations#Operation) * interface. Returns either an `Operation.error` or an `Operation.response` which contains an * `AsyncRecognizeResponse` message. * @@ -446,7 +450,7 @@ public final UnaryCallable asyncRecognizeCalla // AUTO-GENERATED DOCUMENTATION AND METHOD /** - * Perform bidirectional streaming speech-recognition: receive results while sending audio. This + * Performs bidirectional streaming speech recognition: receive results while sending audio. This * method is only available via the gRPC API (not REST). * *

    Sample code: diff --git a/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1beta1/SpeechSettings.java b/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1beta1/SpeechSettings.java index 9e29af446c64..514ec5221f7b 100644 --- a/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1beta1/SpeechSettings.java +++ b/google-cloud-speech/src/main/java/com/google/cloud/speech/spi/v1beta1/SpeechSettings.java @@ -16,6 +16,7 @@ package com.google.cloud.speech.spi.v1beta1; import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; import com.google.api.gax.core.RetrySettings; import com.google.api.gax.grpc.ChannelProvider; import com.google.api.gax.grpc.ClientSettings; @@ -73,12 +74,6 @@ @Generated("by GAPIC v0.0.5") @ExperimentalApi public class SpeechSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "speech.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder().add("https://www.googleapis.com/auth/cloud-platform").build(); @@ -86,6 +81,11 @@ public class SpeechSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final SimpleCallSettings syncRecognizeSettings; private final OperationCallSettings @@ -115,14 +115,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "speech.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -138,15 +133,18 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = SpeechSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty(SpeechSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ @@ -209,9 +207,9 @@ public static class Builder extends ClientSettings.Builder { .setInitialRetryDelay(Duration.millis(100L)) .setRetryDelayMultiplier(1.3) .setMaxRetryDelay(Duration.millis(60000L)) - .setInitialRpcTimeout(Duration.millis(60000L)) + .setInitialRpcTimeout(Duration.millis(190000L)) .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(Duration.millis(60000L)) + .setMaxRpcTimeout(Duration.millis(190000L)) .setTotalTimeout(Duration.millis(600000L)); definitions.put("default", settingsBuilder); RETRY_PARAM_DEFINITIONS = definitions.build(); diff --git a/google-cloud-speech/src/test/java/com/google/cloud/speech/spi/v1/MockSpeech.java b/google-cloud-speech/src/test/java/com/google/cloud/speech/spi/v1/MockSpeech.java new file mode 100644 index 000000000000..3e6e57619f4e --- /dev/null +++ b/google-cloud-speech/src/test/java/com/google/cloud/speech/spi/v1/MockSpeech.java @@ -0,0 +1,59 @@ +/* + * Copyright 2017, Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.speech.spi.v1; + +import com.google.api.gax.testing.MockGrpcService; +import com.google.protobuf.GeneratedMessageV3; +import io.grpc.ServerServiceDefinition; +import java.util.List; + +@javax.annotation.Generated("by GAPIC") +public class MockSpeech implements MockGrpcService { + private final MockSpeechImpl serviceImpl; + + public MockSpeech() { + serviceImpl = new MockSpeechImpl(); + } + + @Override + public List getRequests() { + return serviceImpl.getRequests(); + } + + @Override + public void addResponse(GeneratedMessageV3 response) { + serviceImpl.addResponse(response); + } + + @Override + public void addException(Exception exception) { + serviceImpl.addException(exception); + } + + public void setResponses(List responses) { + serviceImpl.setResponses(responses); + } + + @Override + public ServerServiceDefinition getServiceDefinition() { + return serviceImpl.bindService(); + } + + @Override + public void reset() { + serviceImpl.reset(); + } +} diff --git a/google-cloud-speech/src/test/java/com/google/cloud/speech/spi/v1/MockSpeechImpl.java b/google-cloud-speech/src/test/java/com/google/cloud/speech/spi/v1/MockSpeechImpl.java new file mode 100644 index 000000000000..4192cc102c3a --- /dev/null +++ b/google-cloud-speech/src/test/java/com/google/cloud/speech/spi/v1/MockSpeechImpl.java @@ -0,0 +1,122 @@ +/* + * Copyright 2017, Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.speech.spi.v1; + +import com.google.cloud.speech.v1.LongRunningRecognizeRequest; +import com.google.cloud.speech.v1.RecognizeRequest; +import com.google.cloud.speech.v1.RecognizeResponse; +import com.google.cloud.speech.v1.SpeechGrpc.SpeechImplBase; +import com.google.cloud.speech.v1.StreamingRecognizeRequest; +import com.google.cloud.speech.v1.StreamingRecognizeResponse; +import com.google.longrunning.Operation; +import com.google.protobuf.GeneratedMessageV3; +import io.grpc.stub.StreamObserver; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +@javax.annotation.Generated("by GAPIC") +public class MockSpeechImpl extends SpeechImplBase { + private ArrayList requests; + private Queue responses; + + public MockSpeechImpl() { + requests = new ArrayList<>(); + responses = new LinkedList<>(); + } + + public List getRequests() { + return requests; + } + + public void addResponse(GeneratedMessageV3 response) { + responses.add(response); + } + + public void setResponses(List responses) { + this.responses = new LinkedList(responses); + } + + public void addException(Exception exception) { + responses.add(exception); + } + + public void reset() { + requests = new ArrayList<>(); + responses = new LinkedList<>(); + } + + @Override + public void recognize( + RecognizeRequest request, StreamObserver responseObserver) { + Object response = responses.remove(); + if (response instanceof RecognizeResponse) { + requests.add(request); + responseObserver.onNext((RecognizeResponse) response); + responseObserver.onCompleted(); + } else if (response instanceof Exception) { + responseObserver.onError((Exception) response); + } else { + responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); + } + } + + @Override + public void longRunningRecognize( + LongRunningRecognizeRequest request, StreamObserver responseObserver) { + Object response = responses.remove(); + if (response instanceof Operation) { + requests.add(request); + responseObserver.onNext((Operation) response); + responseObserver.onCompleted(); + } else if (response instanceof Exception) { + responseObserver.onError((Exception) response); + } else { + responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); + } + } + + @Override + public StreamObserver streamingRecognize( + final StreamObserver responseObserver) { + final Object response = responses.remove(); + StreamObserver requestObserver = + new StreamObserver() { + @Override + public void onNext(StreamingRecognizeRequest value) { + if (response instanceof StreamingRecognizeResponse) { + responseObserver.onNext((StreamingRecognizeResponse) response); + } else if (response instanceof Exception) { + responseObserver.onError((Exception) response); + } else { + responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); + } + } + + @Override + public void onError(Throwable t) { + responseObserver.onError(t); + } + + @Override + public void onCompleted() { + responseObserver.onCompleted(); + } + }; + return requestObserver; + } +} diff --git a/google-cloud-speech/src/test/java/com/google/cloud/speech/spi/v1/SpeechClientTest.java b/google-cloud-speech/src/test/java/com/google/cloud/speech/spi/v1/SpeechClientTest.java new file mode 100644 index 000000000000..60badf54b8a4 --- /dev/null +++ b/google-cloud-speech/src/test/java/com/google/cloud/speech/spi/v1/SpeechClientTest.java @@ -0,0 +1,250 @@ +/* + * Copyright 2017, Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.speech.spi.v1; + +import com.google.api.gax.core.ApiStreamObserver; +import com.google.api.gax.grpc.ApiException; +import com.google.api.gax.grpc.StreamingCallable; +import com.google.api.gax.testing.MockGrpcService; +import com.google.api.gax.testing.MockServiceHelper; +import com.google.api.gax.testing.MockStreamObserver; +import com.google.cloud.speech.v1.LongRunningRecognizeRequest; +import com.google.cloud.speech.v1.LongRunningRecognizeResponse; +import com.google.cloud.speech.v1.RecognitionAudio; +import com.google.cloud.speech.v1.RecognitionConfig; +import com.google.cloud.speech.v1.RecognitionConfig.AudioEncoding; +import com.google.cloud.speech.v1.RecognizeRequest; +import com.google.cloud.speech.v1.RecognizeResponse; +import com.google.cloud.speech.v1.StreamingRecognizeRequest; +import com.google.cloud.speech.v1.StreamingRecognizeResponse; +import com.google.longrunning.Operation; +import com.google.protobuf.Any; +import com.google.protobuf.GeneratedMessageV3; +import io.grpc.Status; +import io.grpc.StatusRuntimeException; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ExecutionException; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +@javax.annotation.Generated("by GAPIC") +public class SpeechClientTest { + private static MockSpeech mockSpeech; + private static MockServiceHelper serviceHelper; + private SpeechClient client; + + @BeforeClass + public static void startStaticServer() { + mockSpeech = new MockSpeech(); + serviceHelper = + new MockServiceHelper("in-process-1", Arrays.asList(mockSpeech)); + serviceHelper.start(); + } + + @AfterClass + public static void stopServer() { + serviceHelper.stop(); + } + + @Before + public void setUp() throws IOException { + serviceHelper.reset(); + SpeechSettings settings = + SpeechSettings.defaultBuilder() + .setChannelProvider(serviceHelper.createChannelProvider()) + .build(); + client = SpeechClient.create(settings); + } + + @After + public void tearDown() throws Exception { + client.close(); + } + + @Test + @SuppressWarnings("all") + public void recognizeTest() { + RecognizeResponse expectedResponse = RecognizeResponse.newBuilder().build(); + mockSpeech.addResponse(expectedResponse); + + RecognitionConfig.AudioEncoding encoding = RecognitionConfig.AudioEncoding.FLAC; + int sampleRateHertz = 44100; + String languageCode = "en-US"; + RecognitionConfig config = + RecognitionConfig.newBuilder() + .setEncoding(encoding) + .setSampleRateHertz(sampleRateHertz) + .setLanguageCode(languageCode) + .build(); + String uri = "gs://bucket_name/file_name.flac"; + RecognitionAudio audio = RecognitionAudio.newBuilder().setUri(uri).build(); + + RecognizeResponse actualResponse = client.recognize(config, audio); + Assert.assertEquals(expectedResponse, actualResponse); + + List actualRequests = mockSpeech.getRequests(); + Assert.assertEquals(1, actualRequests.size()); + RecognizeRequest actualRequest = (RecognizeRequest) actualRequests.get(0); + + Assert.assertEquals(config, actualRequest.getConfig()); + Assert.assertEquals(audio, actualRequest.getAudio()); + } + + @Test + @SuppressWarnings("all") + public void recognizeExceptionTest() throws Exception { + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); + mockSpeech.addException(exception); + + try { + RecognitionConfig.AudioEncoding encoding = RecognitionConfig.AudioEncoding.FLAC; + int sampleRateHertz = 44100; + String languageCode = "en-US"; + RecognitionConfig config = + RecognitionConfig.newBuilder() + .setEncoding(encoding) + .setSampleRateHertz(sampleRateHertz) + .setLanguageCode(languageCode) + .build(); + String uri = "gs://bucket_name/file_name.flac"; + RecognitionAudio audio = RecognitionAudio.newBuilder().setUri(uri).build(); + + client.recognize(config, audio); + Assert.fail("No exception raised"); + } catch (ApiException e) { + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); + } + } + + @Test + @SuppressWarnings("all") + public void longRunningRecognizeTest() throws Exception { + LongRunningRecognizeResponse expectedResponse = + LongRunningRecognizeResponse.newBuilder().build(); + Operation resultOperation = + Operation.newBuilder() + .setName("longRunningRecognizeTest") + .setDone(true) + .setResponse(Any.pack(expectedResponse)) + .build(); + mockSpeech.addResponse(resultOperation); + + RecognitionConfig.AudioEncoding encoding = RecognitionConfig.AudioEncoding.FLAC; + int sampleRateHertz = 44100; + String languageCode = "en-US"; + RecognitionConfig config = + RecognitionConfig.newBuilder() + .setEncoding(encoding) + .setSampleRateHertz(sampleRateHertz) + .setLanguageCode(languageCode) + .build(); + String uri = "gs://bucket_name/file_name.flac"; + RecognitionAudio audio = RecognitionAudio.newBuilder().setUri(uri).build(); + + LongRunningRecognizeResponse actualResponse = + client.longRunningRecognizeAsync(config, audio).get(); + Assert.assertEquals(expectedResponse, actualResponse); + + List actualRequests = mockSpeech.getRequests(); + Assert.assertEquals(1, actualRequests.size()); + LongRunningRecognizeRequest actualRequest = (LongRunningRecognizeRequest) actualRequests.get(0); + + Assert.assertEquals(config, actualRequest.getConfig()); + Assert.assertEquals(audio, actualRequest.getAudio()); + } + + @Test + @SuppressWarnings("all") + public void longRunningRecognizeExceptionTest() throws Exception { + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); + mockSpeech.addException(exception); + + try { + RecognitionConfig.AudioEncoding encoding = RecognitionConfig.AudioEncoding.FLAC; + int sampleRateHertz = 44100; + String languageCode = "en-US"; + RecognitionConfig config = + RecognitionConfig.newBuilder() + .setEncoding(encoding) + .setSampleRateHertz(sampleRateHertz) + .setLanguageCode(languageCode) + .build(); + String uri = "gs://bucket_name/file_name.flac"; + RecognitionAudio audio = RecognitionAudio.newBuilder().setUri(uri).build(); + + client.longRunningRecognizeAsync(config, audio).get(); + Assert.fail("No exception raised"); + } catch (ExecutionException e) { + Assert.assertEquals(ApiException.class, e.getCause().getClass()); + ApiException apiException = (ApiException) e.getCause(); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), apiException.getStatusCode()); + } + } + + @Test + @SuppressWarnings("all") + public void streamingRecognizeTest() throws Exception { + StreamingRecognizeResponse expectedResponse = StreamingRecognizeResponse.newBuilder().build(); + mockSpeech.addResponse(expectedResponse); + StreamingRecognizeRequest request = StreamingRecognizeRequest.newBuilder().build(); + + MockStreamObserver responseObserver = new MockStreamObserver<>(); + + StreamingCallable callable = + client.streamingRecognizeCallable(); + ApiStreamObserver requestObserver = + callable.bidiStreamingCall(responseObserver); + + requestObserver.onNext(request); + requestObserver.onCompleted(); + + List actualResponses = responseObserver.future().get(); + Assert.assertEquals(1, actualResponses.size()); + Assert.assertEquals(expectedResponse, actualResponses.get(0)); + } + + @Test + @SuppressWarnings("all") + public void streamingRecognizeExceptionTest() throws Exception { + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); + mockSpeech.addException(exception); + StreamingRecognizeRequest request = StreamingRecognizeRequest.newBuilder().build(); + + MockStreamObserver responseObserver = new MockStreamObserver<>(); + + StreamingCallable callable = + client.streamingRecognizeCallable(); + ApiStreamObserver requestObserver = + callable.bidiStreamingCall(responseObserver); + + requestObserver.onNext(request); + + try { + List actualResponses = responseObserver.future().get(); + Assert.fail("No exception thrown"); + } catch (ExecutionException e) { + Assert.assertTrue(e.getCause() instanceof StatusRuntimeException); + StatusRuntimeException statusException = (StatusRuntimeException) e.getCause(); + Assert.assertEquals(Status.INVALID_ARGUMENT, statusException.getStatus()); + } + } +} diff --git a/google-cloud-speech/src/test/java/com/google/cloud/speech/spi/v1beta1/SpeechClientTest.java b/google-cloud-speech/src/test/java/com/google/cloud/speech/spi/v1beta1/SpeechClientTest.java index d98938f1967b..cc30143dc6de 100644 --- a/google-cloud-speech/src/test/java/com/google/cloud/speech/spi/v1beta1/SpeechClientTest.java +++ b/google-cloud-speech/src/test/java/com/google/cloud/speech/spi/v1beta1/SpeechClientTest.java @@ -107,7 +107,7 @@ public void syncRecognizeTest() { @Test @SuppressWarnings("all") public void syncRecognizeExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockSpeech.addException(exception); try { @@ -121,7 +121,7 @@ public void syncRecognizeExceptionTest() throws Exception { client.syncRecognize(config, audio); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -158,7 +158,7 @@ public void asyncRecognizeTest() throws Exception { @Test @SuppressWarnings("all") public void asyncRecognizeExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockSpeech.addException(exception); try { @@ -174,7 +174,7 @@ public void asyncRecognizeExceptionTest() throws Exception { } catch (ExecutionException e) { Assert.assertEquals(ApiException.class, e.getCause().getClass()); ApiException apiException = (ApiException) e.getCause(); - Assert.assertEquals(Status.INTERNAL.getCode(), apiException.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), apiException.getStatusCode()); } } @@ -205,7 +205,7 @@ public void streamingRecognizeTest() throws Exception { @Test @SuppressWarnings("all") public void streamingRecognizeExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockSpeech.addException(exception); StreamingRecognizeRequest request = StreamingRecognizeRequest.newBuilder().build(); @@ -224,7 +224,7 @@ public void streamingRecognizeExceptionTest() throws Exception { } catch (ExecutionException e) { Assert.assertTrue(e.getCause() instanceof StatusRuntimeException); StatusRuntimeException statusException = (StatusRuntimeException) e.getCause(); - Assert.assertEquals(Status.INTERNAL, statusException.getStatus()); + Assert.assertEquals(Status.INVALID_ARGUMENT, statusException.getStatus()); } } } diff --git a/google-cloud-storage/README.md b/google-cloud-storage/README.md index cdaea8ddf3f0..fb9d9466809a 100644 --- a/google-cloud-storage/README.md +++ b/google-cloud-storage/README.md @@ -22,16 +22,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-storage - 0.10.0-beta + 0.12.0-beta ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-storage:0.10.0-beta' +compile 'com.google.cloud:google-cloud-storage:0.12.0-beta' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-storage" % "0.10.0-beta" +libraryDependencies += "com.google.cloud" % "google-cloud-storage" % "0.12.0-beta" ``` Example Application diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml index f707f1d55397..1a37f43dd6cd 100644 --- a/google-cloud-storage/pom.xml +++ b/google-cloud-storage/pom.xml @@ -12,7 +12,7 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-storage diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/PolicyHelper.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/PolicyHelper.java new file mode 100644 index 000000000000..3da751a9f367 --- /dev/null +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/PolicyHelper.java @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.storage; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.google.api.services.storage.model.Policy.Bindings; +import com.google.cloud.Identity; +import com.google.cloud.Policy; +import com.google.cloud.Role; + +/** + * Helper for converting between the Policy model provided by the API and the Policy model provided + * by this library. + */ +class PolicyHelper { + + static Policy convertFromApiPolicy(com.google.api.services.storage.model.Policy apiPolicy) { + Policy.Builder policyBuilder = Policy.newBuilder(); + for (Bindings binding : apiPolicy.getBindings()) { + for (String member : binding.getMembers()) { + policyBuilder.addIdentity(Role.of(binding.getRole()), Identity.valueOf(member)); + } + } + return policyBuilder.setEtag(apiPolicy.getEtag()).build(); + } + + static com.google.api.services.storage.model.Policy convertToApiPolicy(Policy policy) { + List bindings = new ArrayList<>(policy.getBindings().size()); + for (Map.Entry> entry : policy.getBindings().entrySet()) { + List members = new ArrayList<>(entry.getValue().size()); + for (Identity identity : entry.getValue()) { + members.add(identity.strValue()); + } + bindings.add(new Bindings().setMembers(members).setRole(entry.getKey().getValue())); + } + return new com.google.api.services.storage.model.Policy() + .setBindings(bindings) + .setEtag(policy.getEtag()); + } + + private PolicyHelper() { + // Intentionally left blank. + } +} diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 2cf7c1f001bd..65a30add97e8 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -19,11 +19,25 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import java.io.InputStream; +import java.io.Serializable; +import java.net.URL; +import java.security.Key; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.TimeUnit; + import com.google.auth.ServiceAccountSigner; import com.google.auth.ServiceAccountSigner.SigningException; import com.google.cloud.FieldSelector; import com.google.cloud.FieldSelector.Helper; import com.google.cloud.Page; +import com.google.cloud.Policy; import com.google.cloud.ReadChannel; import com.google.cloud.Service; import com.google.cloud.WriteChannel; @@ -35,19 +49,6 @@ import com.google.common.collect.Lists; import com.google.common.io.BaseEncoding; -import java.io.InputStream; -import java.io.Serializable; -import java.net.URL; -import java.security.Key; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.TimeUnit; - /** * An interface for Google Cloud Storage. * @@ -2369,4 +2370,57 @@ public static Builder newBuilder() { * @throws StorageException upon failure */ List listAcls(BlobId blob); + + /** + * Gets the IAM policy for the provided bucket. + * + *

    Example of getting the IAM policy for a bucket. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * Policy policy = storage.getPolicy(bucketName);
    +   * }
    + * + * @throws StorageException upon failure + */ + Policy getPolicy(String bucket); + + /** + * Updates the IAM policy on the specified bucket. + * + *

    Example of updating the IAM policy on a bucket. + *

    {@code
    +   * // We want to make all objects in our bucket publicly readable.
    +   * String bucketName = "my_unique_bucket";
    +   * Policy currentPolicy = storage.getPolicy(bucketName);
    +   * Policy updatedPolicy =
    +   *     storage.updatePolicy(
    +   *         bucketName,
    +   *         currentPolicy.toBuilder()
    +   *             .addIdentity(StorageRoles.objectViewer(), Identity.allUsers())
    +   *             .build());
    +   * }
    + * + * @throws StorageException upon failure + */ + Policy updatePolicy(String bucket, Policy policy); + + /** + * Tests whether the caller holds the permissions on the specified bucket. Returns a list of + * booleans in the same placement and order in which the permissions were specified. + * + *

    Example of testing permissions on a bucket. + *

     {@code
    +   * String bucketName = "my_unique_bucket";
    +   * List response =
    +   *     storage.testPermissions(
    +   *         bucket,
    +   *         ImmutableList.of("storage.buckets.get", "storage.buckets.getIamPolicy"));
    +   * for (boolean hasPermission : response) {
    +   *   // Do something with permission test response
    +   * }
    +   * }
    + * + * @throws StorageException upon failure + */ + List testPermissions(String bucket, List permissions); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageClass.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageClass.java index bac2790f0d5b..8f529173707d 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageClass.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageClass.java @@ -44,5 +44,10 @@ public enum StorageClass { /** * Standard storage class. */ - STANDARD + STANDARD, + + /** + * Durable Reduced Availability (deprecated) + */ + DURABLE_REDUCED_AVAILABILITY, } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index c2ec81e683e9..30a41fd81185 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -17,6 +17,8 @@ package com.google.cloud.storage; import static com.google.cloud.RetryHelper.runWithRetries; +import static com.google.cloud.storage.PolicyHelper.convertFromApiPolicy; +import static com.google.cloud.storage.PolicyHelper.convertToApiPolicy; import static com.google.cloud.storage.spi.v1.StorageRpc.Option.DELIMITER; import static com.google.cloud.storage.spi.v1.StorageRpc.Option.IF_GENERATION_MATCH; import static com.google.cloud.storage.spi.v1.StorageRpc.Option.IF_GENERATION_NOT_MATCH; @@ -31,15 +33,32 @@ import static com.google.common.base.Preconditions.checkState; import static java.nio.charset.StandardCharsets.UTF_8; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; + import com.google.api.services.storage.model.BucketAccessControl; import com.google.api.services.storage.model.ObjectAccessControl; import com.google.api.services.storage.model.StorageObject; +import com.google.api.services.storage.model.TestIamPermissionsResponse; import com.google.auth.ServiceAccountSigner; import com.google.cloud.BaseService; import com.google.cloud.BatchResult; import com.google.cloud.Page; import com.google.cloud.PageImpl; import com.google.cloud.PageImpl.NextPageFetcher; +import com.google.cloud.Policy; import com.google.cloud.ReadChannel; import com.google.cloud.RetryHelper.RetryHelperException; import com.google.cloud.storage.Acl.Entity; @@ -49,6 +68,7 @@ import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -57,20 +77,6 @@ import com.google.common.net.UrlEscapers; import com.google.common.primitives.Ints; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; - final class StorageImpl extends BaseService implements Storage { private static final byte[] EMPTY_BYTE_ARRAY = {}; @@ -854,6 +860,58 @@ public List call() { throw StorageException.translateAndThrow(e); } } + + @Override + public Policy getPolicy(final String bucket) { + try { + return convertFromApiPolicy(runWithRetries(new Callable() { + @Override + public com.google.api.services.storage.model.Policy call() { + return storageRpc.getPolicy(bucket); + } + }, getOptions().getRetrySettings(), EXCEPTION_HANDLER, getOptions().getClock())); + } catch (RetryHelperException e){ + throw StorageException.translateAndThrow(e); + } + } + + @Override + public Policy updatePolicy(final String bucket, final Policy policy) { + try { + return convertFromApiPolicy(runWithRetries(new Callable() { + @Override + public com.google.api.services.storage.model.Policy call() { + return storageRpc.updatePolicy(bucket, convertToApiPolicy(policy)); + } + }, getOptions().getRetrySettings(), EXCEPTION_HANDLER, getOptions().getClock())); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + + @Override + public List testPermissions(final String bucket, final List permissions) { + try { + TestIamPermissionsResponse response = runWithRetries(new Callable() { + @Override + public TestIamPermissionsResponse call() { + return storageRpc.testPermissions(bucket, permissions); + } + }, getOptions().getRetrySettings(), EXCEPTION_HANDLER, getOptions().getClock()); + final Set heldPermissions = + response.getPermissions() != null + ? ImmutableSet.copyOf(response.getPermissions()) + : ImmutableSet.of(); + return Lists.transform(permissions, new Function() { + @Override + public Boolean apply(String permission) { + return heldPermissions.contains(permission); + } + }); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } private static void addToOptionMap(StorageRpc.Option option, T defaultValue, Map map) { diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java index 7d11be03b25a..15981d0ac075 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java @@ -48,7 +48,9 @@ import com.google.api.services.storage.model.ComposeRequest.SourceObjects.ObjectPreconditions; import com.google.api.services.storage.model.ObjectAccessControl; import com.google.api.services.storage.model.Objects; +import com.google.api.services.storage.model.Policy; import com.google.api.services.storage.model.StorageObject; +import com.google.api.services.storage.model.TestIamPermissionsResponse; import com.google.cloud.BaseServiceException; import com.google.cloud.HttpTransportOptions; import com.google.cloud.storage.StorageException; @@ -834,4 +836,31 @@ public List listAcls(String bucket, String object, Long gen throw translate(ex); } } + + @Override + public Policy getPolicy(String bucket) { + try { + return storage.buckets().getIamPolicy(bucket).execute(); + } catch (IOException ex) { + throw translate(ex); + } + } + + @Override + public Policy updatePolicy(String bucket, Policy policy) { + try { + return storage.buckets().setIamPolicy(bucket, policy).execute(); + } catch (IOException ex) { + throw translate(ex); + } + } + + @Override + public TestIamPermissionsResponse testPermissions(String bucket, List permissions) { + try { + return storage.buckets().testIamPermissions(bucket, permissions).execute(); + } catch (IOException ex) { + throw translate(ex); + } + } } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java index 91b9601181ea..31a1ca4896aa 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java @@ -19,7 +19,9 @@ import com.google.api.services.storage.model.Bucket; import com.google.api.services.storage.model.BucketAccessControl; import com.google.api.services.storage.model.ObjectAccessControl; +import com.google.api.services.storage.model.Policy; import com.google.api.services.storage.model.StorageObject; +import com.google.api.services.storage.model.TestIamPermissionsResponse; import com.google.cloud.ServiceRpc; import com.google.cloud.storage.StorageException; @@ -427,4 +429,25 @@ void write(String uploadId, byte[] toWrite, int toWriteOffset, long destOffset, * @throws StorageException upon failure */ List listAcls(String bucket, String object, Long generation); + + /** + * Returns the IAM policy for the specified bucket. + * + * @throws StorageException upon failure + */ + Policy getPolicy(String bucket); + + /** + * Updates the IAM policy for the specified bucket. + * + * @throws StorageException upon failure + */ + Policy updatePolicy(String bucket, Policy policy); + + /** + * Tests whether the caller holds the specified permissions for the specified bucket. + * + * @throws StorageException upon failure + */ + TestIamPermissionsResponse testPermissions(String bucket, List permissions); } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/PolicyHelperTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/PolicyHelperTest.java new file mode 100644 index 000000000000..70b66f7b19d5 --- /dev/null +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/PolicyHelperTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.storage; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.google.api.services.storage.model.Policy.Bindings; +import com.google.cloud.Identity; +import com.google.cloud.Policy; +import com.google.cloud.storage.testing.ApiPolicyMatcher; +import com.google.common.collect.ImmutableList; + +public class PolicyHelperTest { + + private static final String ETAG = "CAE="; + + @Test + public void testEquivalence() { + Policy libPolicy = + Policy.newBuilder() + .addIdentity(StorageRoles.objectViewer(), Identity.allUsers()) + .addIdentity( + StorageRoles.objectAdmin(), + Identity.user("test1@gmail.com"), + Identity.user("test2@gmail.com")) + .setEtag(ETAG) + .build(); + com.google.api.services.storage.model.Policy apiPolicy = + new com.google.api.services.storage.model.Policy() + .setBindings(ImmutableList.of( + new Bindings() + .setMembers(ImmutableList.of("allUsers")) + .setRole("roles/storage.objectViewer"), + new Bindings() + .setMembers( + ImmutableList.of( + "user:test1@gmail.com", + "user:test2@gmail.com")) + .setRole("roles/storage.objectAdmin"))) + .setEtag(ETAG); + + Policy actualLibPolicy = PolicyHelper.convertFromApiPolicy(apiPolicy); + com.google.api.services.storage.model.Policy actualApiPolicy = + PolicyHelper.convertToApiPolicy(libPolicy); + + assertEquals(libPolicy, actualLibPolicy); + assertTrue(new ApiPolicyMatcher(apiPolicy).matches(actualApiPolicy)); + } +} diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java index 397a167503ee..1b72623ee92a 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java @@ -16,6 +16,9 @@ package com.google.cloud.storage; +import static com.google.cloud.storage.testing.ApiPolicyMatcher.eqApiPolicy; +import static org.easymock.EasyMock.cmp; +import static org.easymock.EasyMock.eq; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -25,11 +28,49 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; +import java.nio.ByteBuffer; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import java.security.spec.EncodedKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import javax.crypto.spec.SecretKeySpec; + +import org.easymock.Capture; +import org.easymock.EasyMock; +import org.easymock.LogicalOperator; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + import com.google.api.client.googleapis.json.GoogleJsonError; import com.google.api.gax.core.ApiClock; +import com.google.api.services.storage.model.Policy.Bindings; import com.google.api.services.storage.model.StorageObject; +import com.google.api.services.storage.model.TestIamPermissionsResponse; import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.cloud.Identity; import com.google.cloud.Page; +import com.google.cloud.Policy; import com.google.cloud.ReadChannel; import com.google.api.gax.core.RetrySettings; import com.google.cloud.ServiceOptions; @@ -53,39 +94,6 @@ import com.google.common.io.BaseEncoding; import com.google.common.net.UrlEscapers; -import org.easymock.Capture; -import org.easymock.EasyMock; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLDecoder; -import java.nio.ByteBuffer; -import java.security.InvalidKeyException; -import java.security.Key; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.Signature; -import java.security.SignatureException; -import java.security.spec.EncodedKeySpec; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import javax.crypto.spec.SecretKeySpec; - public class StorageImplTest { private static final String BUCKET_NAME1 = "b1"; @@ -243,6 +251,33 @@ public class StorageImplTest { private static final Map ENCRYPTION_KEY_OPTIONS = ImmutableMap.of(StorageRpc.Option.CUSTOMER_SUPPLIED_KEY, BASE64_KEY); + // IAM policies + private static final String POLICY_ETAG1 = "CAE="; + private static final String POLICY_ETAG2 = "CAI="; + private static final Policy LIB_POLICY1 = + Policy.newBuilder() + .addIdentity(StorageRoles.objectViewer(), Identity.allUsers()) + .addIdentity( + StorageRoles.objectAdmin(), + Identity.user("test1@gmail.com"), + Identity.user("test2@gmail.com")) + .setEtag(POLICY_ETAG1) + .build(); + + private static final com.google.api.services.storage.model.Policy API_POLICY1 = + new com.google.api.services.storage.model.Policy() + .setBindings(ImmutableList.of( + new Bindings() + .setMembers(ImmutableList.of("allUsers")) + .setRole("roles/storage.objectViewer"), + new Bindings() + .setMembers( + ImmutableList.of( + "user:test1@gmail.com", + "user:test2@gmail.com")) + .setRole("roles/storage.objectAdmin"))) + .setEtag(POLICY_ETAG1); + private static final String PRIVATE_KEY_STRING = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoG" + "BAL2xolH1zrISQ8+GzOV29BNjjzq4/HIP8Psd1+cZb81vDklSF+95wB250MSE0BDc81pvIMwj5OmIfLg1NY6uB" @@ -1947,6 +1982,106 @@ public void testListBlobAcl() { assertEquals(ImmutableList.of(ACL, OTHER_ACL), acls); } + @Test + public void testGetPolicy() { + EasyMock.expect(storageRpcMock.getPolicy(BUCKET_NAME1)).andReturn(API_POLICY1); + EasyMock.replay(storageRpcMock); + initializeService(); + assertEquals(LIB_POLICY1, storage.getPolicy(BUCKET_NAME1)); + } + + @Test + public void testUpdatePolicy() { + com.google.api.services.storage.model.Policy preCommitApiPolicy = + new com.google.api.services.storage.model.Policy() + .setBindings(ImmutableList.of( + new Bindings() + .setMembers(ImmutableList.of("allUsers")) + .setRole("roles/storage.objectViewer"), + new Bindings() + .setMembers( + ImmutableList.of( + "user:test1@gmail.com", + "user:test2@gmail.com")) + .setRole("roles/storage.objectAdmin"), + new Bindings() + .setMembers(ImmutableList.of("group:test-group@gmail.com")) + .setRole("roles/storage.admin"))) + .setEtag(POLICY_ETAG1); + // postCommitApiPolicy is identical but for the etag, which has been updated. + com.google.api.services.storage.model.Policy postCommitApiPolicy = + new com.google.api.services.storage.model.Policy() + .setBindings(ImmutableList.of( + new Bindings() + .setMembers(ImmutableList.of("allUsers")) + .setRole("roles/storage.objectViewer"), + new Bindings() + .setMembers( + ImmutableList.of( + "user:test1@gmail.com", + "user:test2@gmail.com")) + .setRole("roles/storage.objectAdmin"), + new Bindings() + .setMembers(ImmutableList.of("group:test-group@gmail.com")) + .setRole("roles/storage.admin"))) + .setEtag(POLICY_ETAG2); + Policy postCommitLibPolicy = + Policy.newBuilder() + .addIdentity(StorageRoles.objectViewer(), Identity.allUsers()) + .addIdentity( + StorageRoles.objectAdmin(), + Identity.user("test1@gmail.com"), + Identity.user("test2@gmail.com")) + .addIdentity(StorageRoles.admin(), Identity.group("test-group@gmail.com")) + .setEtag(POLICY_ETAG2) + .build(); + + EasyMock.expect(storageRpcMock.getPolicy(BUCKET_NAME1)).andReturn(API_POLICY1); + EasyMock.expect( + storageRpcMock.updatePolicy( + eq(BUCKET_NAME1), + eqApiPolicy(preCommitApiPolicy))) + .andReturn(postCommitApiPolicy); + EasyMock.replay(storageRpcMock); + initializeService(); + + Policy currentPolicy = storage.getPolicy(BUCKET_NAME1); + Policy updatedPolicy = + storage.updatePolicy( + BUCKET_NAME1, + currentPolicy.toBuilder() + .addIdentity(StorageRoles.admin(), Identity.group("test-group@gmail.com")) + .build()); + assertEquals(updatedPolicy, postCommitLibPolicy); + } + + @Test + public void testTestPermissionsNull() { + ImmutableList expectedPermissions = ImmutableList.of(false, false, false); + ImmutableList checkedPermissions = + ImmutableList.of("storage.buckets.get", "storage.buckets.getIamPolicy", "storage.objects.list"); + + EasyMock.expect(storageRpcMock.testPermissions(BUCKET_NAME1, checkedPermissions)) + .andReturn(new TestIamPermissionsResponse()); + EasyMock.replay(storageRpcMock); + initializeService(); + assertEquals(expectedPermissions, storage.testPermissions(BUCKET_NAME1, checkedPermissions)); + } + + @Test + public void testTestPermissionsNonNull() { + ImmutableList expectedPermissions = ImmutableList.of(true, false, true); + ImmutableList checkedPermissions = + ImmutableList.of("storage.buckets.get", "storage.buckets.getIamPolicy", "storage.objects.list"); + + EasyMock.expect(storageRpcMock.testPermissions(BUCKET_NAME1, checkedPermissions)) + .andReturn(new TestIamPermissionsResponse() + .setPermissions(ImmutableList.of("storage.objects.list", "storage.buckets.get"))); + EasyMock.replay(storageRpcMock); + initializeService(); + assertEquals(expectedPermissions, storage.testPermissions(BUCKET_NAME1, checkedPermissions)); + } + @Test public void testRetryableException() { BlobId blob = BlobId.of(BUCKET_NAME1, BLOB_NAME1); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index 48ae816e8c3d..9215058595a5 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -16,6 +16,7 @@ package com.google.cloud.storage.it; +import static com.google.common.collect.Sets.newHashSet; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -25,7 +26,38 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.nio.ByteBuffer; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.GZIPInputStream; + +import javax.crypto.spec.SecretKeySpec; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.cloud.Identity; import com.google.cloud.Page; +import com.google.cloud.Policy; import com.google.cloud.ReadChannel; import com.google.cloud.RestorableState; import com.google.cloud.WriteChannel; @@ -46,6 +78,7 @@ import com.google.cloud.storage.StorageBatchResult; import com.google.cloud.storage.StorageClass; import com.google.cloud.storage.StorageException; +import com.google.cloud.storage.StorageRoles; import com.google.cloud.storage.testing.RemoteStorageHelper; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -56,37 +89,9 @@ import com.google.common.io.BaseEncoding; import com.google.common.io.ByteStreams; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.nio.ByteBuffer; -import java.security.Key; -import java.security.NoSuchAlgorithmException; -import java.security.spec.InvalidKeySpecException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.zip.GZIPInputStream; - -import javax.crypto.spec.SecretKeySpec; - public class ITStorageTest { + private static RemoteStorageHelper remoteStorageHelper; private static Storage storage; private static final Logger log = Logger.getLogger(ITStorageTest.class.getName()); @@ -104,8 +109,8 @@ public class ITStorageTest { @BeforeClass public static void beforeClass() throws NoSuchAlgorithmException, InvalidKeySpecException { - RemoteStorageHelper helper = RemoteStorageHelper.create(); - storage = helper.getOptions().getService(); + remoteStorageHelper = RemoteStorageHelper.create(); + storage = remoteStorageHelper.getOptions().getService(); storage.create(BucketInfo.of(BUCKET)); } @@ -1440,4 +1445,49 @@ public void testReadCompressedBlob() throws IOException { } blob.delete(); } + + @Test + public void testBucketPolicy() { + String projectId = remoteStorageHelper.getOptions().getProjectId(); + Identity projectOwner = Identity.projectOwner(projectId); + Identity projectEditor = Identity.projectEditor(projectId); + Identity projectViewer = Identity.projectViewer(projectId); + Map> bindingsWithoutPublicRead = + ImmutableMap.of( + StorageRoles.legacyBucketOwner(), (Set) newHashSet(projectOwner, projectEditor), + StorageRoles.legacyBucketReader(), newHashSet(projectViewer)); + Map> bindingsWithPublicRead = + ImmutableMap.of( + StorageRoles.legacyBucketOwner(), (Set) newHashSet(projectOwner, projectEditor), + StorageRoles.legacyBucketReader(), newHashSet(projectViewer), + StorageRoles.legacyObjectReader(), newHashSet(Identity.allUsers())); + + // Validate getting policy. + Policy currentPolicy = storage.getPolicy(BUCKET); + assertEquals(bindingsWithoutPublicRead, currentPolicy.getBindings()); + + // Validate updating policy. + Policy updatedPolicy = + storage.updatePolicy( + BUCKET, + currentPolicy.toBuilder() + .addIdentity(StorageRoles.legacyObjectReader(), Identity.allUsers()) + .build()); + assertEquals(bindingsWithPublicRead, updatedPolicy.getBindings()); + Policy revertedPolicy = + storage.updatePolicy( + BUCKET, + updatedPolicy.toBuilder() + .removeIdentity(StorageRoles.legacyObjectReader(), Identity.allUsers()) + .build()); + assertEquals(bindingsWithoutPublicRead, revertedPolicy.getBindings()); + + // Validate testing permissions. + List expectedPermissions = ImmutableList.of(true, true); + assertEquals( + expectedPermissions, + storage.testPermissions( + BUCKET, + ImmutableList.of("storage.buckets.getIamPolicy", "storage.buckets.setIamPolicy"))); + } } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/ApiPolicyMatcher.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/ApiPolicyMatcher.java new file mode 100644 index 000000000000..501b61b4294e --- /dev/null +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/ApiPolicyMatcher.java @@ -0,0 +1,104 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.storage.testing; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.easymock.EasyMock; +import org.easymock.IArgumentMatcher; + +import com.google.api.services.storage.model.Policy; +import com.google.api.services.storage.model.Policy.Bindings; +import com.google.common.collect.ImmutableSet; + +/** + * Matches two {@link Policy} instances, which may have lists of {@link Bindings} that are not in + * the same order but which are still logically equivalent. + */ +public class ApiPolicyMatcher implements IArgumentMatcher { + + private final Map> expectedBindings; + private final String expectedEtag; + + public ApiPolicyMatcher(Policy expected) { + expectedBindings = toMap(expected.getBindings()); + expectedEtag = expected.getEtag(); + } + + @Override + public boolean matches(Object object) { + if (!(object instanceof Policy)) { + return false; + } + Policy actual = (Policy) object; + Map> actualBindings = toMap(actual.getBindings()); + String actualEtag = actual.getEtag(); + + if (expectedEtag == null) { + if (actualEtag != null) { + return false; + } + } else { + if (!expectedEtag.equals(actual.getEtag())) { + return false; + } + } + + if (expectedBindings.size() != actualBindings.size()) { + return false; + } + + for (Map.Entry> entry : expectedBindings.entrySet()) { + String role = entry.getKey(); + Set expectedMembers = entry.getValue(); + Set actualMembers = actualBindings.get(role); + if (!expectedMembers.equals(actualMembers)) { + return false; + } + } + + return true; + } + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("eqApiPolicy("); + buffer.append("etag="); + buffer.append(expectedEtag); + buffer.append(",bindings="); + buffer.append(expectedBindings); + buffer.append(")"); + } + + public static Policy eqApiPolicy(Policy in) { + EasyMock.reportMatcher(new ApiPolicyMatcher(in)); + return null; + } + + private Map> toMap(List bindings) { + Map> mapBindings = new HashMap<>(); + if (bindings != null) { + for (Bindings binding : bindings) { + mapBindings.put(binding.getRole(), ImmutableSet.copyOf(binding.getMembers())); + } + } + return mapBindings; + } +} diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/ApiPolicyMatcherTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/ApiPolicyMatcherTest.java new file mode 100644 index 000000000000..b1b6856ed1f4 --- /dev/null +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/ApiPolicyMatcherTest.java @@ -0,0 +1,115 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.storage.testing; + +import static com.google.cloud.storage.testing.ApiPolicyMatcher.eqApiPolicy; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.easymock.EasyMock; +import org.junit.Test; + +import com.google.api.services.storage.model.Policy; +import com.google.api.services.storage.model.Policy.Bindings; +import com.google.common.collect.ImmutableList; + +public class ApiPolicyMatcherTest { + + private static interface PolicyAcceptor { + int accept(Policy policy); + } + + private static final String ETAG = "CAE="; + private static final Policy API_POLICY_1 = + new Policy() + .setBindings(ImmutableList.of( + new Bindings() + .setMembers(ImmutableList.of("allUsers")) + .setRole("roles/storage.objectViewer"), + new Bindings() + .setMembers( + ImmutableList.of( + "user:test1@gmail.com", + "user:test2@gmail.com")) + .setRole("roles/storage.objectAdmin"), + new Bindings() + .setMembers(ImmutableList.of("group:test-group@gmail.com")) + .setRole("roles/storage.admin"))) + .setEtag(ETAG); + private static final Policy API_POLICY_2 = + new Policy() + .setBindings(ImmutableList.of( + new Bindings() + .setMembers(ImmutableList.of("group:test-group@gmail.com")) + .setRole("roles/storage.admin"), + new Bindings() + .setMembers(ImmutableList.of("allUsers")) + .setRole("roles/storage.objectViewer"), + new Bindings() + .setMembers( + ImmutableList.of( + "user:test2@gmail.com", + "user:test1@gmail.com")) + .setRole("roles/storage.objectAdmin"))) + .setEtag(ETAG); + private static final Policy API_POLICY_MISSING_BINDINGS = + new Policy().setEtag(ETAG); + private static final Policy API_POLICY_MISSING_ETAG = + new Policy() + .setBindings(ImmutableList.of( + new Bindings() + .setMembers(ImmutableList.of("group:test-group@gmail.com")) + .setRole("roles/storage.admin"), + new Bindings() + .setMembers(ImmutableList.of("allUsers")) + .setRole("roles/storage.objectViewer"), + new Bindings() + .setMembers( + ImmutableList.of( + "user:test2@gmail.com", + "user:test1@gmail.com")) + .setRole("roles/storage.objectAdmin"))); + + @Test + public void testEquivalence() { + assertMatch(API_POLICY_1, API_POLICY_2); + assertMatch(API_POLICY_2, API_POLICY_1); + assertNoMatch(API_POLICY_1, API_POLICY_MISSING_BINDINGS); + assertNoMatch(API_POLICY_MISSING_BINDINGS, API_POLICY_1); + assertNoMatch(API_POLICY_1, API_POLICY_MISSING_ETAG); + assertNoMatch(API_POLICY_MISSING_ETAG, API_POLICY_1); + assertNoMatch(API_POLICY_MISSING_BINDINGS, API_POLICY_MISSING_ETAG); + assertNoMatch(API_POLICY_MISSING_ETAG, API_POLICY_MISSING_BINDINGS); + } + + private static void assertMatch(Policy expected, Policy actual) { + assertTrue(new ApiPolicyMatcher(expected).matches(actual)); + } + + private static void assertNoMatch(Policy expected, Policy actual) { + assertFalse(new ApiPolicyMatcher(expected).matches(actual)); + } + + @Test + public void testStaticMocker() { + PolicyAcceptor mock = EasyMock.createMock(PolicyAcceptor.class); + EasyMock.expect(mock.accept(eqApiPolicy(API_POLICY_1))).andReturn(0); + EasyMock.replay(mock); + mock.accept(API_POLICY_2); + EasyMock.verify(mock); + } +} diff --git a/google-cloud-trace/pom.xml b/google-cloud-trace/pom.xml index b3daadf6bb53..38927afaf265 100644 --- a/google-cloud-trace/pom.xml +++ b/google-cloud-trace/pom.xml @@ -11,10 +11,11 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-trace + ${project.version} @@ -87,6 +88,22 @@ + + org.codehaus.mojo + properties-maven-plugin + 1.0-alpha-2 + + + generate-resources + + write-project-properties + + + ${project.build.outputDirectory}/project.properties + + + + org.codehaus.mojo build-helper-maven-plugin diff --git a/google-cloud-trace/src/main/java/com/google/cloud/trace/spi/v1/TraceServiceSettings.java b/google-cloud-trace/src/main/java/com/google/cloud/trace/spi/v1/TraceServiceSettings.java index 3b8f45b62dc1..32fe957aafa7 100644 --- a/google-cloud-trace/src/main/java/com/google/cloud/trace/spi/v1/TraceServiceSettings.java +++ b/google-cloud-trace/src/main/java/com/google/cloud/trace/spi/v1/TraceServiceSettings.java @@ -18,6 +18,7 @@ import static com.google.cloud.trace.spi.v1.PagedResponseWrappers.ListTracesPagedResponse; import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; import com.google.api.gax.core.RetrySettings; import com.google.api.gax.grpc.CallContext; import com.google.api.gax.grpc.ChannelProvider; @@ -78,12 +79,6 @@ @Generated("by GAPIC v0.0.5") @ExperimentalApi public class TraceServiceSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "cloudtrace.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() @@ -95,6 +90,11 @@ public class TraceServiceSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final SimpleCallSettings patchTracesSettings; private final SimpleCallSettings getTraceSettings; private final PagedCallSettings @@ -121,14 +121,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "cloudtrace.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -144,15 +139,19 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = TraceServiceSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty( + TraceServiceSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ diff --git a/google-cloud-trace/src/test/java/com/google/cloud/trace/spi/v1/TraceServiceClientTest.java b/google-cloud-trace/src/test/java/com/google/cloud/trace/spi/v1/TraceServiceClientTest.java index 0874976eab4a..e312d100a984 100644 --- a/google-cloud-trace/src/test/java/com/google/cloud/trace/spi/v1/TraceServiceClientTest.java +++ b/google-cloud-trace/src/test/java/com/google/cloud/trace/spi/v1/TraceServiceClientTest.java @@ -97,7 +97,7 @@ public void patchTracesTest() { @Test @SuppressWarnings("all") public void patchTracesExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockTraceService.addException(exception); try { @@ -107,7 +107,7 @@ public void patchTracesExceptionTest() throws Exception { client.patchTraces(projectId, traces); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -137,7 +137,7 @@ public void getTraceTest() { @Test @SuppressWarnings("all") public void getTraceExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockTraceService.addException(exception); try { @@ -147,7 +147,7 @@ public void getTraceExceptionTest() throws Exception { client.getTrace(projectId, traceId); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } @@ -182,7 +182,7 @@ public void listTracesTest() { @Test @SuppressWarnings("all") public void listTracesExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockTraceService.addException(exception); try { @@ -191,7 +191,7 @@ public void listTracesExceptionTest() throws Exception { client.listTraces(projectId); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } } diff --git a/google-cloud-translate/README.md b/google-cloud-translate/README.md index 00d72f1a7aaf..33294327b4d8 100644 --- a/google-cloud-translate/README.md +++ b/google-cloud-translate/README.md @@ -1,7 +1,7 @@ -Google Cloud Java Client for Translate +Google Cloud Java Client for Translation ==================================== -Java idiomatic client for [Google Translate](https://cloud.google.com/translate/). +Java idiomatic client for [Google Translation](https://cloud.google.com/translate/). [![Build Status](https://travis-ci.org/GoogleCloudPlatform/google-cloud-java.svg?branch=master)](https://travis-ci.org/GoogleCloudPlatform/google-cloud-java) [![Coverage Status](https://coveralls.io/repos/GoogleCloudPlatform/google-cloud-java/badge.svg?branch=master)](https://coveralls.io/r/GoogleCloudPlatform/google-cloud-java?branch=master) @@ -22,63 +22,63 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-translate - 0.10.0-alpha + 0.12.0-alpha ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-translate:0.10.0-alpha' +compile 'com.google.cloud:google-cloud-translate:0.12.0-alpha' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-translate" % "0.10.0-alpha" +libraryDependencies += "com.google.cloud" % "google-cloud-translate" % "0.12.0-alpha" ``` Example Application ------------------- -[`TranslateExample`](../google-cloud-examples/src/main/java/com/google/cloud/examples/translate/TranslateExample.java) is a simple command line interface that provides some of Google Translate's functionality. Read more about using the application on the [`TranslateExample` docs page](https://googlecloudplatform.github.io/google-cloud-java/apidocs/?com/google/cloud/examples/translate/TranslateExample.html). +[`TranslateExample`](../google-cloud-examples/src/main/java/com/google/cloud/examples/translate/TranslateExample.java) is a simple command line interface that provides some of Google Translation's functionality. Read more about using the application on the [`TranslateExample` docs page](https://googlecloudplatform.github.io/google-cloud-java/apidocs/?com/google/cloud/examples/translate/TranslateExample.html). Authentication -------------- -Google Translate requires an API key to be passed with every request. For instructions on how to -get an API key follow the [Translate quickstart](https://cloud.google.com/translate/v2/quickstart). +Google Translation requires an API key to be passed with every request. For instructions on how to +get an API key follow the [Translation quickstart](https://cloud.google.com/translate/v2/quickstart). -About Google Translate +About Google Translation -------------------- -[Google Translate][google-translate] provides a simple programmatic interface for translating an -arbitrary string into any supported language. Translate is highly responsive, so websites and -applications can integrate with Translate API for fast, dynamic translation of source text from the +[Google Translation][google-translate] provides a simple programmatic interface for translating an +arbitrary string into any supported language. Translation is highly responsive, so websites and +applications can integrate with Translation API for fast, dynamic translation of source text from the source language to a target language (e.g., French to English). Language detection is also available In cases where the source language is unknown. -See the [Translate quickstart](https://cloud.google.com/translate/v2/quickstart) for more details -on how to activate Google Translate for your project. +See the [Translation quickstart](https://cloud.google.com/translate/v2/quickstart) for more details +on how to activate Google Translation for your project. -See the ``google-cloud`` API [Translate documentation][translate-api] to learn how to interact with -the Google Translate using this Client Library. +See the ``google-cloud`` API [Translation documentation][translate-api] to learn how to interact with +the Google Translation using this Client Library. Getting Started --------------- #### Prerequisites For this tutorial, you need a [Google Developers Console](https://console.developers.google.com/) -project with "Translate API" enabled via the console's API Manager. You also need to enable +project with "Translation API" enabled via the console's API Manager. You also need to enable billing via the [Google Developers Console](https://console.developers.google.com/). Finally, you must set up the local development environment by [installing the Google Cloud SDK](https://cloud.google.com/sdk/) and running the following command in command line: `gcloud auth application-default login`. Alternatively, you can authenticate -Translate requests using an API key. See -[Translate quickstart](https://cloud.google.com/translate/v2/quickstart) for more details. +Translation requests using an API key. See +[Translation quickstart](https://cloud.google.com/translate/v2/quickstart) for more details. #### Installation and setup You'll need to obtain the `google-cloud-translate` library. See the [Quickstart](#quickstart) section to add `google-cloud-translate` as a dependency in your code. #### Creating an authorized service object -To make authenticated requests to Google Translate, you must create a service object with +To make authenticated requests to Google Translation, you must create a service object with credentials or with an API key. The simplest way to authenticate is to use [Application Default Credentials](https://developers.google.com/identity/protocols/application-default-credentials). These credentials are automatically inferred from your environment, so you only need the following @@ -93,15 +93,15 @@ Translate translate = TranslateOptions.getDefaultInstance().getService(); Notice that this code can be also used with an API key. By default, an API key is looked for in the `GOOGLE_API_KEY` environment variable. Once the API key is set, you can make API calls by invoking -methods on the Translate service created via `TranslateOptions.getDefaultInstance().getService()`. +methods on the Translation service created via `TranslateOptions.getDefaultInstance().getService()`. You can also explicitly set the API key as follows: ```java -Translate translate = TranslateOptions.newBuilder().setApiKey("myKey").getService(); +Translate translate = TranslateOptions.newBuilder().setApiKey("myKey").build().getService(); ``` #### Detecting language -With Google Translate you can detect the language of some text. The service will provide you with +With Google Translation you can detect the language of some text. The service will provide you with the code of the detected language and a level of confidence. Add the following import at the top of your file: @@ -117,7 +117,7 @@ String detectedLanguage = detection.getLanguage(); ``` #### Translating text -Google translate allows you to translate some text. When translating one or more texts you can +Google translation allows you to translate some text. When translating one or more texts you can either provide the source language or let the service detect it for you. Add the following imports at the top of your file: @@ -156,7 +156,7 @@ Java 7 or above is required for using this client. Testing ------- -This library has tools to help make tests for code using Cloud Translate. +This library has tools to help make tests for code using Cloud Translation. See [TESTING] to read more about testing. diff --git a/google-cloud-translate/pom.xml b/google-cloud-translate/pom.xml index 0bd7d5559777..f78b447d362a 100644 --- a/google-cloud-translate/pom.xml +++ b/google-cloud-translate/pom.xml @@ -2,16 +2,17 @@ 4.0.0 google-cloud-translate + ${beta.version} jar - Google Cloud Translate + Google Cloud Translation https://github.com/GoogleCloudPlatform/google-cloud-java/tree/master/google-cloud-translate - Java idiomatic client for Google Translate. + Java idiomatic client for Google Translation. com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-translate diff --git a/google-cloud-translate/src/main/java/com/google/cloud/translate/Language.java b/google-cloud-translate/src/main/java/com/google/cloud/translate/Language.java index a6c626c0fbff..1d79518b35b1 100644 --- a/google-cloud-translate/src/main/java/com/google/cloud/translate/Language.java +++ b/google-cloud-translate/src/main/java/com/google/cloud/translate/Language.java @@ -24,7 +24,7 @@ import java.util.Objects; /** - * Information about a language supported by Google Translate. Objects of this class contain + * Information about a language supported by Google Translation. Objects of this class contain * language's code and the language name. * * @see diff --git a/google-cloud-translate/src/main/java/com/google/cloud/translate/Translate.java b/google-cloud-translate/src/main/java/com/google/cloud/translate/Translate.java index bd09a9e615ec..0c08e481da6a 100644 --- a/google-cloud-translate/src/main/java/com/google/cloud/translate/Translate.java +++ b/google-cloud-translate/src/main/java/com/google/cloud/translate/Translate.java @@ -22,9 +22,9 @@ import java.util.List; /** - * An interface for Google Translate. + * An interface for Google Translation. * - * @see Google Translate + * @see Google Translation */ public interface Translate extends Service { @@ -64,7 +64,7 @@ private TranslateOption(TranslateRpc.Option rpcOption, String value) { } /** - * Returns an option for setting the source language. If not provided, Google Translate will try + * Returns an option for setting the source language. If not provided, Google Translation will try * to detect the language of the text to translate. * * @param sourceLanguage the source language code @@ -85,7 +85,7 @@ public static TranslateOption targetLanguage(String targetLanguage) { /** * Sets the language translation model. You can use this parameter to take advantage of Neural - * Machine Translation. Possible values are {@code base} and {@code nmt}. Google Translate could + * Machine Translation. Possible values are {@code base} and {@code nmt}. Google Translation could * use a different model to translate your text, use {@link Translation#getModel()} to know * which model was used for translation. Please notice that you must be whitelisted to use this * option, otherwise translation will fail. @@ -98,7 +98,7 @@ public static TranslateOption model(String model) { } /** - * Returns the list of languages supported by Google Translate. If + * Returns the list of languages supported by Google Translation. If * {@link LanguageListOption#targetLanguage(String)} is provided, {@link Language#getName()} * values are localized according to the provided target language. If no such option is passed, * {@link Language#getName()} values are localized according to diff --git a/google-cloud-translate/src/main/java/com/google/cloud/translate/TranslateException.java b/google-cloud-translate/src/main/java/com/google/cloud/translate/TranslateException.java index de176255add9..5d47e4a9522a 100644 --- a/google-cloud-translate/src/main/java/com/google/cloud/translate/TranslateException.java +++ b/google-cloud-translate/src/main/java/com/google/cloud/translate/TranslateException.java @@ -24,7 +24,7 @@ import java.util.Set; /** - * Google Translate service exception. + * Google Translation service exception. */ public class TranslateException extends BaseServiceException { diff --git a/google-cloud-translate/src/main/java/com/google/cloud/translate/Translation.java b/google-cloud-translate/src/main/java/com/google/cloud/translate/Translation.java index 0acd10857654..3527203f64e9 100644 --- a/google-cloud-translate/src/main/java/com/google/cloud/translate/Translation.java +++ b/google-cloud-translate/src/main/java/com/google/cloud/translate/Translation.java @@ -27,7 +27,7 @@ /** * Information about a translation. Objects of this class contain the translated text and the source * language's code. Source language's code can be the one provided by the user (if any) or the one - * detected by the Google Translate service. + * detected by the Google Translation service. * * Translating Text */ @@ -63,7 +63,7 @@ public String getTranslatedText() { /** * Returns the language code of the source text. If no source language was provided this value is - * the source language as detected by the Google Translate service. + * the source language as detected by the Google Translation service. */ public String getSourceLanguage() { return sourceLanguage; diff --git a/google-cloud-translate/src/main/java/com/google/cloud/translate/package-info.java b/google-cloud-translate/src/main/java/com/google/cloud/translate/package-info.java index 3fe371993708..ef5bc85a8ead 100644 --- a/google-cloud-translate/src/main/java/com/google/cloud/translate/package-info.java +++ b/google-cloud-translate/src/main/java/com/google/cloud/translate/package-info.java @@ -15,7 +15,7 @@ */ /** - * A client to Google Translate. + * A client to Google Translation. * *

    Here's a simple usage example for using google-cloud. This example shows how to detect the * language of some text and how to translate some text. The example assumes that the diff --git a/google-cloud-translate/src/main/java/com/google/cloud/translate/spi/TranslateRpcFactory.java b/google-cloud-translate/src/main/java/com/google/cloud/translate/spi/TranslateRpcFactory.java index 3da42ee836a6..be1338e7d22c 100644 --- a/google-cloud-translate/src/main/java/com/google/cloud/translate/spi/TranslateRpcFactory.java +++ b/google-cloud-translate/src/main/java/com/google/cloud/translate/spi/TranslateRpcFactory.java @@ -20,7 +20,7 @@ import com.google.cloud.translate.TranslateOptions; /** - * An interface for Translate RPC factory. + * An interface for Translation RPC factory. * Implementation will be loaded via {@link java.util.ServiceLoader}. */ public interface TranslateRpcFactory extends ServiceRpcFactory { diff --git a/google-cloud-translate/src/main/java/com/google/cloud/translate/spi/v2/TranslateRpc.java b/google-cloud-translate/src/main/java/com/google/cloud/translate/spi/v2/TranslateRpc.java index 9f4193421c1f..3078dd70b14f 100644 --- a/google-cloud-translate/src/main/java/com/google/cloud/translate/spi/v2/TranslateRpc.java +++ b/google-cloud-translate/src/main/java/com/google/cloud/translate/spi/v2/TranslateRpc.java @@ -52,7 +52,7 @@ String getString(Map options) { } /** - * Returns a list of the languages supported by Google Translate. + * Returns a list of the languages supported by Google Translation. * * @param optionMap options to listing language translations */ diff --git a/google-cloud-translate/src/main/java/com/google/cloud/translate/testing/RemoteTranslateHelper.java b/google-cloud-translate/src/main/java/com/google/cloud/translate/testing/RemoteTranslateHelper.java index 4d0ade6ac4d9..7d91d0b427e1 100644 --- a/google-cloud-translate/src/main/java/com/google/cloud/translate/testing/RemoteTranslateHelper.java +++ b/google-cloud-translate/src/main/java/com/google/cloud/translate/testing/RemoteTranslateHelper.java @@ -52,7 +52,7 @@ public TranslateOptions getOptions() { /** * Creates a {@code RemoteTranslateHelper} object for the given API key. * - * @param apiKey API key used to issue requests to Google Translate. + * @param apiKey API key used to issue requests to Google Translation. */ public static RemoteTranslateHelper create(String apiKey) { HttpTransportOptions transportOptions = TranslateOptions.getDefaultHttpTransportOptions(); diff --git a/google-cloud-translate/src/main/java/com/google/cloud/translate/testing/package-info.java b/google-cloud-translate/src/main/java/com/google/cloud/translate/testing/package-info.java index ff798c563896..573d9b1a22ca 100644 --- a/google-cloud-translate/src/main/java/com/google/cloud/translate/testing/package-info.java +++ b/google-cloud-translate/src/main/java/com/google/cloud/translate/testing/package-info.java @@ -15,7 +15,7 @@ */ /** - * A testing helper for Google Translate. + * A testing helper for Google Translation. * *

    A simple usage example: *

    Before the test: diff --git a/google-cloud-vision/pom.xml b/google-cloud-vision/pom.xml index 5503d133aba9..557587cc979b 100644 --- a/google-cloud-vision/pom.xml +++ b/google-cloud-vision/pom.xml @@ -12,10 +12,11 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT google-cloud-vision + ${project.version} @@ -88,6 +89,22 @@ + + org.codehaus.mojo + properties-maven-plugin + 1.0-alpha-2 + + + generate-resources + + write-project-properties + + + ${project.build.outputDirectory}/project.properties + + + + org.codehaus.mojo build-helper-maven-plugin diff --git a/google-cloud-vision/src/main/java/com/google/cloud/vision/spi/v1/ImageAnnotatorSettings.java b/google-cloud-vision/src/main/java/com/google/cloud/vision/spi/v1/ImageAnnotatorSettings.java index ee49a95714f9..e708b3cd54d6 100644 --- a/google-cloud-vision/src/main/java/com/google/cloud/vision/spi/v1/ImageAnnotatorSettings.java +++ b/google-cloud-vision/src/main/java/com/google/cloud/vision/spi/v1/ImageAnnotatorSettings.java @@ -16,6 +16,7 @@ package com.google.cloud.vision.spi.v1; import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.api.gax.core.PropertiesProvider; import com.google.api.gax.core.RetrySettings; import com.google.api.gax.grpc.ChannelProvider; import com.google.api.gax.grpc.ClientSettings; @@ -67,12 +68,6 @@ @Generated("by GAPIC v0.0.5") @ExperimentalApi public class ImageAnnotatorSettings extends ClientSettings { - /** The default address of the service. */ - private static final String DEFAULT_SERVICE_ADDRESS = "vision.googleapis.com"; - - /** The default port of the service. */ - private static final int DEFAULT_SERVICE_PORT = 443; - /** The default scopes of the service. */ private static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder().add("https://www.googleapis.com/auth/cloud-platform").build(); @@ -80,6 +75,11 @@ public class ImageAnnotatorSettings extends ClientSettings { private static final String DEFAULT_GAPIC_NAME = "gapic"; private static final String DEFAULT_GAPIC_VERSION = ""; + private static final String PROPERTIES_FILE = "/project.properties"; + private static final String META_VERSION_KEY = "artifact.version"; + + private static String gapicVersion; + private final SimpleCallSettings batchAnnotateImagesSettings; @@ -94,14 +94,9 @@ public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuild return InstantiatingExecutorProvider.newBuilder(); } - /** Returns the default service address. */ - public static String getDefaultServiceAddress() { - return DEFAULT_SERVICE_ADDRESS; - } - - /** Returns the default service port. */ - public static int getDefaultServicePort() { - return DEFAULT_SERVICE_PORT; + /** Returns the default service endpoint. */ + public static String getDefaultEndpoint() { + return "vision.googleapis.com:443"; } /** Returns the default service scopes. */ @@ -117,15 +112,19 @@ public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilde /** Returns a builder for the default ChannelProvider for this service. */ public static InstantiatingChannelProvider.Builder defaultChannelProviderBuilder() { return InstantiatingChannelProvider.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) + .setEndpoint(getDefaultEndpoint()) .setGeneratorHeader(DEFAULT_GAPIC_NAME, getGapicVersion()) .setCredentialsProvider(defaultCredentialsProviderBuilder().build()); } private static String getGapicVersion() { - String packageVersion = ImageAnnotatorSettings.class.getPackage().getImplementationVersion(); - return packageVersion != null ? packageVersion : DEFAULT_GAPIC_VERSION; + if (gapicVersion == null) { + gapicVersion = + PropertiesProvider.loadProperty( + ImageAnnotatorSettings.class, PROPERTIES_FILE, META_VERSION_KEY); + gapicVersion = gapicVersion == null ? DEFAULT_GAPIC_VERSION : gapicVersion; + } + return gapicVersion; } /** Returns a builder for this class with recommended defaults. */ diff --git a/google-cloud-vision/src/test/java/com/google/cloud/vision/spi/v1/ImageAnnotatorClientTest.java b/google-cloud-vision/src/test/java/com/google/cloud/vision/spi/v1/ImageAnnotatorClientTest.java index f1129b74f967..68ae3cfd6fff 100644 --- a/google-cloud-vision/src/test/java/com/google/cloud/vision/spi/v1/ImageAnnotatorClientTest.java +++ b/google-cloud-vision/src/test/java/com/google/cloud/vision/spi/v1/ImageAnnotatorClientTest.java @@ -90,7 +90,7 @@ public void batchAnnotateImagesTest() { @Test @SuppressWarnings("all") public void batchAnnotateImagesExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INTERNAL); + StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); mockImageAnnotator.addException(exception); try { @@ -99,7 +99,7 @@ public void batchAnnotateImagesExceptionTest() throws Exception { client.batchAnnotateImages(requests); Assert.fail("No exception raised"); } catch (ApiException e) { - Assert.assertEquals(Status.INTERNAL.getCode(), e.getStatusCode()); + Assert.assertEquals(Status.INVALID_ARGUMENT.getCode(), e.getStatusCode()); } } } diff --git a/google-cloud/README.md b/google-cloud/README.md index a57021583d93..480774e2f36a 100644 --- a/google-cloud/README.md +++ b/google-cloud/README.md @@ -27,16 +27,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud - 0.10.0-alpha + 0.12.0-alpha ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud:0.10.0-alpha' +compile 'com.google.cloud:google-cloud:0.12.0-alpha' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud" % "0.10.0-alpha" +libraryDependencies += "com.google.cloud" % "google-cloud" % "0.12.0-alpha" ``` Troubleshooting diff --git a/google-cloud/pom.xml b/google-cloud/pom.xml index b0ec5ca4ff7c..d62a09a47753 100644 --- a/google-cloud/pom.xml +++ b/google-cloud/pom.xml @@ -11,7 +11,7 @@ com.google.cloud google-cloud-pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT @@ -47,7 +47,7 @@ ${project.groupId} google-cloud-language - ${project.version} + ${beta.version} ${project.groupId} @@ -87,7 +87,7 @@ ${project.groupId} google-cloud-translate - ${project.version} + ${beta.version} ${project.groupId} diff --git a/pom.xml b/pom.xml index e78b87aba329..1cfb34f8bee5 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-pom pom - 0.10.1-alpha-SNAPSHOT + 0.12.1-alpha-SNAPSHOT Google Cloud https://github.com/GoogleCloudPlatform/google-cloud-java @@ -90,12 +90,12 @@ UTF-8 UTF-8 github - 0.6.0 + 0.6.1 1.0.3 - 0.6.1 + 0.8.1 0.1.5 - 0.10.1-alpha-SNAPSHOT - 0.10.1-beta-SNAPSHOT + 0.12.1-alpha-SNAPSHOT + 0.12.1-beta-SNAPSHOT ${beta.version} google-cloud @@ -120,6 +120,15 @@ google-cloud-trace google-cloud-translate google-cloud-vision + + + + + + @@ -433,7 +442,9 @@ http://googleapis.github.io/gax-java/${gax.version}/apidocs/ http://googleapis.github.io/googleapis/java/grpc-google-iam-v1/${generatedProto.version}/apidocs/ http://googleapis.github.io/googleapis/java/grpc-google-cloud-error-reporting-v1beta1/${generatedProto.version}/apidocs/ - http://googleapis.github.io/googleapis/java/grpc-google-cloud-language-v1/${generatedProto.version}/apidocs/ + + http://googleapis.github.io/googleapis/java/grpc-google-cloud-language-v1/0.1.6/apidocs/ + http://googleapis.github.io/googleapis/java/grpc-google-cloud-language-v1beta2/0.1.6/apidocs/ http://googleapis.github.io/googleapis/java/grpc-google-cloud-logging-v2/${generatedProto.version}/apidocs/ http://googleapis.github.io/googleapis/java/grpc-google-cloud-monitoring-v3/${generatedProto.version}/apidocs/ http://googleapis.github.io/googleapis/java/grpc-google-cloud-pubsub-v1/${generatedProto.version}/apidocs/ diff --git a/testing/google-cloud-appengine-flex-compat/pom.xml b/testing/google-cloud-appengine-flex-compat/pom.xml new file mode 100644 index 000000000000..02f2ef9beb71 --- /dev/null +++ b/testing/google-cloud-appengine-flex-compat/pom.xml @@ -0,0 +1,67 @@ + + + + google-cloud-pom + com.google.cloud + 0.12.1-alpha-SNAPSHOT + ../.. + + + 4.0.0 + war + google-cloud-appengine-flex-compat + + + 1.9.51 + 1.2.1 + 9.3.8.v20160314 + 1.7 + + + + + ${project.groupId} + google-cloud-managed-test + ${project.version} + + + com.google.appengine + appengine-api-1.0-sdk + ${appengine.sdk.version} + + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty.maven.plugin} + + + + org.apache.maven.plugins + 3.5.1 + maven-compiler-plugin + + ${java.source.version} + ${java.source.version} + + + + com.google.cloud.tools + appengine-maven-plugin + ${appengine.maven.plugin} + + 1 + + + + + diff --git a/testing/google-cloud-appengine-flex-compat/src/main/webapp/WEB-INF/appengine-web.xml b/testing/google-cloud-appengine-flex-compat/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 000000000000..666ecfc4bf5f --- /dev/null +++ b/testing/google-cloud-appengine-flex-compat/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,18 @@ + + + GCLOUD_PROJECT_ID_HERE + flex-compat + 1 + true + flex + + + + + 1 + + + 1 + 4 + + diff --git a/testing/google-cloud-appengine-flex-compat/src/main/webapp/WEB-INF/web.xml b/testing/google-cloud-appengine-flex-compat/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000000..5fae1f07743a --- /dev/null +++ b/testing/google-cloud-appengine-flex-compat/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,6 @@ + + + diff --git a/testing/google-cloud-appengine-flex-compat/src/main/webapp/index.html b/testing/google-cloud-appengine-flex-compat/src/main/webapp/index.html new file mode 100644 index 000000000000..4cd4135f9823 --- /dev/null +++ b/testing/google-cloud-appengine-flex-compat/src/main/webapp/index.html @@ -0,0 +1,13 @@ + +google-cloud-java managed environments tests executor + +

    Enter fully qualified test class names to execute. One class per line, use '#' for comments.

    +
    + +
    + +
    + + diff --git a/testing/google-cloud-appengine-flex-custom/pom.xml b/testing/google-cloud-appengine-flex-custom/pom.xml new file mode 100644 index 000000000000..9e4532953def --- /dev/null +++ b/testing/google-cloud-appengine-flex-custom/pom.xml @@ -0,0 +1,51 @@ + + + + google-cloud-pom + com.google.cloud + 0.12.1-alpha-SNAPSHOT + ../.. + + + 4.0.0 + war + google-cloud-appengine-flex-custom + + + 1.2.1 + 9.3.8.v20160314 + + + + + ${project.groupId} + google-cloud-managed-test + ${project.version} + + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty.maven.plugin} + + + + com.google.cloud.tools + appengine-maven-plugin + ${appengine.maven.plugin} + + 1 + + + + + diff --git a/testing/google-cloud-appengine-flex-custom/src/main/appengine/app.yaml b/testing/google-cloud-appengine-flex-custom/src/main/appengine/app.yaml new file mode 100644 index 000000000000..de7271d2a175 --- /dev/null +++ b/testing/google-cloud-appengine-flex-custom/src/main/appengine/app.yaml @@ -0,0 +1,15 @@ +runtime: custom +env: flex + +handlers: +- url: /.* + script: this field is required, but ignored + +service: flex-custom + +manual_scaling: + instances: 1 + +resources: + cpu: 1 + memory_gb: 6 diff --git a/testing/google-cloud-appengine-flex-custom/src/main/docker/Dockerfile b/testing/google-cloud-appengine-flex-custom/src/main/docker/Dockerfile new file mode 100644 index 000000000000..cbd990e15bb3 --- /dev/null +++ b/testing/google-cloud-appengine-flex-custom/src/main/docker/Dockerfile @@ -0,0 +1,2 @@ +FROM gcr.io/google_appengine/jetty +ADD google-cloud-appengine-flex-custom-0.12.1-alpha-SNAPSHOT.war $JETTY_BASE/webapps/root.war diff --git a/testing/google-cloud-appengine-flex-custom/src/main/webapp/WEB-INF/web.xml b/testing/google-cloud-appengine-flex-custom/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000000..5fae1f07743a --- /dev/null +++ b/testing/google-cloud-appengine-flex-custom/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,6 @@ + + + diff --git a/testing/google-cloud-appengine-flex-custom/src/main/webapp/index.html b/testing/google-cloud-appengine-flex-custom/src/main/webapp/index.html new file mode 100644 index 000000000000..4cd4135f9823 --- /dev/null +++ b/testing/google-cloud-appengine-flex-custom/src/main/webapp/index.html @@ -0,0 +1,13 @@ + +google-cloud-java managed environments tests executor + +

    Enter fully qualified test class names to execute. One class per line, use '#' for comments.

    +
    + +
    + +
    + + diff --git a/testing/google-cloud-appengine-flex-java/pom.xml b/testing/google-cloud-appengine-flex-java/pom.xml new file mode 100644 index 000000000000..a49638bd9a79 --- /dev/null +++ b/testing/google-cloud-appengine-flex-java/pom.xml @@ -0,0 +1,51 @@ + + + + google-cloud-pom + com.google.cloud + 0.12.1-alpha-SNAPSHOT + ../.. + + + 4.0.0 + war + google-cloud-appengine-flex-java + + + 1.2.1 + 9.3.8.v20160314 + + + + + ${project.groupId} + google-cloud-managed-test + ${project.version} + + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty.maven.plugin} + + + + com.google.cloud.tools + appengine-maven-plugin + ${appengine.maven.plugin} + + 1 + + + + + diff --git a/testing/google-cloud-appengine-flex-java/src/main/appengine/app.yaml b/testing/google-cloud-appengine-flex-java/src/main/appengine/app.yaml new file mode 100644 index 000000000000..ff8ef73aa0a7 --- /dev/null +++ b/testing/google-cloud-appengine-flex-java/src/main/appengine/app.yaml @@ -0,0 +1,15 @@ +runtime: java +env: flex + +handlers: +- url: /.* + script: this field is required, but ignored + +service: flex-java + +manual_scaling: + instances: 1 + +resources: + cpu: 1 + memory_gb: 6 diff --git a/testing/google-cloud-appengine-flex-java/src/main/webapp/WEB-INF/web.xml b/testing/google-cloud-appengine-flex-java/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000000..5fae1f07743a --- /dev/null +++ b/testing/google-cloud-appengine-flex-java/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,6 @@ + + + diff --git a/testing/google-cloud-appengine-flex-java/src/main/webapp/index.html b/testing/google-cloud-appengine-flex-java/src/main/webapp/index.html new file mode 100644 index 000000000000..4cd4135f9823 --- /dev/null +++ b/testing/google-cloud-appengine-flex-java/src/main/webapp/index.html @@ -0,0 +1,13 @@ + +google-cloud-java managed environments tests executor + +

    Enter fully qualified test class names to execute. One class per line, use '#' for comments.

    +
    + +
    + +
    + + diff --git a/testing/google-cloud-appengine-java8/pom.xml b/testing/google-cloud-appengine-java8/pom.xml new file mode 100644 index 000000000000..86c92ed46a1e --- /dev/null +++ b/testing/google-cloud-appengine-java8/pom.xml @@ -0,0 +1,58 @@ + + + + google-cloud-pom + com.google.cloud + 0.12.1-alpha-SNAPSHOT + ../.. + + + 4.0.0 + war + google-cloud-appengine-java8 + + + 1.9.51 + 9.3.8.v20160314 + 1.8 + + + + + ${project.groupId} + google-cloud-managed-test + ${project.version} + + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty.maven.plugin} + + + + org.apache.maven.plugins + 3.5.1 + maven-compiler-plugin + + ${java.source.version} + ${java.source.version} + + + + com.google.appengine + appengine-maven-plugin + ${appengine.sdk.version} + + + + diff --git a/testing/google-cloud-appengine-java8/src/main/webapp/WEB-INF/appengine-web.xml b/testing/google-cloud-appengine-java8/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 000000000000..0010fc434171 --- /dev/null +++ b/testing/google-cloud-appengine-java8/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,16 @@ + + + GCLOUD_PROJECT_ID_HERE + std-java8 + 1 + java8 + true + B8 + + 1 + + native + + + + diff --git a/testing/google-cloud-appengine-java8/src/main/webapp/WEB-INF/web.xml b/testing/google-cloud-appengine-java8/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000000..5fae1f07743a --- /dev/null +++ b/testing/google-cloud-appengine-java8/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,6 @@ + + + diff --git a/testing/google-cloud-appengine-java8/src/main/webapp/index.html b/testing/google-cloud-appengine-java8/src/main/webapp/index.html new file mode 100644 index 000000000000..4cd4135f9823 --- /dev/null +++ b/testing/google-cloud-appengine-java8/src/main/webapp/index.html @@ -0,0 +1,13 @@ + +google-cloud-java managed environments tests executor + +

    Enter fully qualified test class names to execute. One class per line, use '#' for comments.

    +
    + +
    + +
    + + diff --git a/testing/google-cloud-managed-test/pom.xml b/testing/google-cloud-managed-test/pom.xml new file mode 100644 index 000000000000..50cd4c3c4098 --- /dev/null +++ b/testing/google-cloud-managed-test/pom.xml @@ -0,0 +1,228 @@ + + + + google-cloud-pom + com.google.cloud + 0.12.1-alpha-SNAPSHOT + ../../pom.xml + + 4.0.0 + + google-cloud-managed-test + + + + ${project.groupId} + google-cloud-bigquery + ${beta.version} + + + ${project.groupId} + google-cloud-bigquery + ${beta.version} + test-jar + + + + ${project.groupId} + google-cloud-compute + ${project.version} + + + ${project.groupId} + google-cloud-compute + ${project.version} + test-jar + + + + ${project.groupId} + google-cloud-core + ${project.version} + + + ${project.groupId} + google-cloud-core + ${project.version} + test-jar + + + + ${project.groupId} + google-cloud-datastore + ${beta.version} + + + ${project.groupId} + google-cloud-datastore + ${beta.version} + test-jar + + + + ${project.groupId} + google-cloud-dns + ${project.version} + + + ${project.groupId} + google-cloud-dns + ${project.version} + test-jar + + + + ${project.groupId} + google-cloud-errorreporting + ${project.version} + + + ${project.groupId} + google-cloud-errorreporting + ${project.version} + test-jar + + + + ${project.groupId} + google-cloud-language + ${beta.version} + + + ${project.groupId} + google-cloud-language + ${beta.version} + test-jar + + + + ${project.groupId} + google-cloud-logging + ${beta.version} + + + ${project.groupId} + google-cloud-logging + ${beta.version} + test-jar + + + + ${project.groupId} + google-cloud-monitoring + ${project.version} + + + ${project.groupId} + google-cloud-monitoring + ${project.version} + test-jar + + + + ${project.groupId} + google-cloud-pubsub + ${project.version} + + + ${project.groupId} + google-cloud-pubsub + ${project.version} + test-jar + + + + ${project.groupId} + google-cloud-resourcemanager + ${project.version} + + + ${project.groupId} + google-cloud-resourcemanager + ${project.version} + test-jar + + + + + ${project.groupId} + google-cloud-speech + ${project.version} + + + ${project.groupId} + google-cloud-speech + ${project.version} + test-jar + + + + ${project.groupId} + google-cloud-storage + ${storage.version} + + + ${project.groupId} + google-cloud-storage + ${storage.version} + test-jar + + + + ${project.groupId} + google-cloud-trace + ${project.version} + + + ${project.groupId} + google-cloud-trace + ${project.version} + test-jar + + + + ${project.groupId} + google-cloud-translate + ${beta.version} + + + ${project.groupId} + google-cloud-translate + ${beta.version} + test-jar + + + + ${project.groupId} + google-cloud-vision + ${beta.version} + + + ${project.groupId} + google-cloud-vision + ${beta.version} + test-jar + + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + + junit + junit + 4.12 + + + + org.easymock + easymock + 3.4 + + + diff --git a/testing/google-cloud-managed-test/src/main/java/com/google/cloud/managed/test/GaeGcjTestServlet.java b/testing/google-cloud-managed-test/src/main/java/com/google/cloud/managed/test/GaeGcjTestServlet.java new file mode 100644 index 000000000000..46dd58cd5b85 --- /dev/null +++ b/testing/google-cloud-managed-test/src/main/java/com/google/cloud/managed/test/GaeGcjTestServlet.java @@ -0,0 +1,118 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.managed.test; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet(value = "/test") +public class GaeGcjTestServlet extends HttpServlet { + + private static final long serialVersionUID = 523885428311420041L; + + private final ThreadPoolExecutor executor = + new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); + private volatile GcjTestRunner testRunner; + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + try { + String classNames = req.getParameter("classes"); + PrintWriter out = resp.getWriter(); + List> testClasses = loadClasses(classNames.split("[\\r\\n]+")); + String output = runTests(testClasses, req, resp); + out.append(output); + out.close(); + } catch (Exception e) { + throw new ServletException(e); + } + } + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + PrintWriter out = resp.getWriter(); + out.append(getTestOutput(req, resp)); + out.close(); + } + + private List> loadClasses(String... classNames) throws ClassNotFoundException { + List> classes = new ArrayList<>(); + for (String className : classNames) { + String cn = className.trim(); + if (!cn.isEmpty() && !cn.startsWith("#")) { + classes.add(Class.forName(cn)); + } + } + return classes; + } + + private String runTests( + List> classes, HttpServletRequest req, HttpServletResponse resp) { + synchronized (executor) { + resp.setContentType("text/html"); + if (executor.getActiveCount() > 0) { + return "Cannot start new test: the previous test hasn't completed yet.

    " + + "The active test progress is at " + + req.getRequestURL() + + "."; + } + + testRunner = new GcjTestRunner(classes); + executor.execute(testRunner); + return "Test started. Check progress at " + + req.getRequestURL() + + ""; + } + } + + private String getTestOutput(HttpServletRequest req, HttpServletResponse resp) { + synchronized (executor) { + if (testRunner != null) { + resp.setContentType("text"); + return testRunner.getOutput(); + } + resp.setContentType("text/html"); + int urlUriLenDiff = req.getRequestURL().length() - req.getRequestURI().length(); + String link = req.getRequestURL().substring(0, urlUriLenDiff); + return "Test hasn't been started yet. Go to " + + link + + " to start a new test"; + } + } + + @Override + public void destroy() { + executor.shutdownNow(); + super.destroy(); + } +} diff --git a/testing/google-cloud-managed-test/src/main/java/com/google/cloud/managed/test/GaeInfoServlet.java b/testing/google-cloud-managed-test/src/main/java/com/google/cloud/managed/test/GaeInfoServlet.java new file mode 100644 index 000000000000..a6f78735cce5 --- /dev/null +++ b/testing/google-cloud-managed-test/src/main/java/com/google/cloud/managed/test/GaeInfoServlet.java @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.managed.test; + +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Map; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet(value = "/info") +public class GaeInfoServlet extends HttpServlet { + + private static final long serialVersionUID = -3598229312089602597L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.setContentType("text"); + PrintWriter out = resp.getWriter(); + + ClassLoader cl = getClass().getClassLoader(); + out.append("CLASS LOADER:\n\n"); + out.append("Name: ").append(cl != null ? cl.getClass().getName() : null).append('\n'); + if (cl instanceof URLClassLoader) { + URLClassLoader urlCl = (URLClassLoader) cl; + out.append("Urls: ").append('\n'); + for (URL url : urlCl.getURLs()) { + out.append(url.toString()).append('\n'); + } + } + + out.append("\nENVIRONMENT VARIABLES:\n\n"); + Map envVars = System.getenv(); + for (Map.Entry entry : envVars.entrySet()) { + out.append(entry.getKey()).append("=").append(entry.getValue()).append('\n'); + } + + out.append("\n\nSYSTEM PROPERTIES:\n\n"); + System.getProperties().list(out); + + out.close(); + } +} diff --git a/testing/google-cloud-managed-test/src/main/java/com/google/cloud/managed/test/GcjTestRunner.java b/testing/google-cloud-managed-test/src/main/java/com/google/cloud/managed/test/GcjTestRunner.java new file mode 100644 index 000000000000..de427771e60e --- /dev/null +++ b/testing/google-cloud-managed-test/src/main/java/com/google/cloud/managed/test/GcjTestRunner.java @@ -0,0 +1,65 @@ +/* + * Copyright 2017 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.managed.test; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; +import org.junit.internal.TextListener; +import org.junit.runner.JUnitCore; + +public class GcjTestRunner implements Runnable { + private final JUnitCore unit; + private final ByteArrayOutputStream resultBytes; + private final PrintStream resultStream; + private final List> classes; + + public GcjTestRunner(List> classes) { + this.unit = new JUnitCore(); + this.resultBytes = new ByteArrayOutputStream(); + this.resultStream = new PrintStream(this.resultBytes); + this.unit.addListener(new TextListener(this.resultStream)); + this.classes = new ArrayList<>(classes); + } + + @Override + public void run() { + synchronized (resultStream) { + resultBytes.reset(); + } + for (Class clazz : classes) { + resultStream.append("\n").append("Running ").append(clazz.getName()); + ClassLoader classLoader = clazz.getClassLoader(); + resultStream.append(" (loaded by ").append(classLoader.getClass().getName()).append(")\n\n"); + unit.run(clazz); + } + + resultStream.append("ALL TESTS COMPLETED"); + } + + public String getOutput() { + //works because PrintStream is thread safe synchronizing on "this". + synchronized (resultStream) { + try { + return resultBytes.toString("UTF-8"); + } catch (UnsupportedEncodingException e) { + return null; + } + } + } +} diff --git a/utilities/update_pom_version.sh b/utilities/update_pom_version.sh index a4e84f136c26..6b5c9563246d 100755 --- a/utilities/update_pom_version.sh +++ b/utilities/update_pom_version.sh @@ -15,7 +15,7 @@ CURRENT_VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate CURRENT_VERSION_BASE=$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -Ev '(^\[|\w+:)' | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+') # Get list of directories for which pom.xml must be updated -module_folders=($(find . -maxdepth 2 -type d | sed -E -n "/^\.\/(google-cloud-contrib\/)?google-cloud(-[a-z]+)+$/p") . ./google-cloud) +module_folders=($(find . -maxdepth 2 -type d | sed -E -n "/^\.\/(google-cloud-contrib\/|testing\/)?google-cloud(-[a-z0-9]+)+$/p") . ./google-cloud) CURRENT_SNAPSHOT="" if [ "${CURRENT_VERSION##*-}" == "SNAPSHOT" ]; then @@ -39,6 +39,10 @@ echo "Changing version from ${CURRENT_VERSION_BASE}-*${CURRENT_SNAPSHOT} to ${NE for item in ${module_folders[*]} do sed -ri "0,/$CURRENT_VERSION_BASE/s/${CURRENT_VERSION_BASE}(-[a-z]+)?[^<]*/${NEW_VERSION_BASE}\1${NEW_SNAPSHOT}/" ${item}/pom.xml + if [ -w ${item}/src/main/docker/Dockerfile ] + then + sed -ri "s/${CURRENT_VERSION_BASE}(-[a-z]+)?(-SNAPSHOT)?/${NEW_VERSION_BASE}\1${NEW_SNAPSHOT}/" ${item}/src/main/docker/Dockerfile + fi done sed -ri "0,/$CURRENT_VERSION_BASE/s/${CURRENT_VERSION_BASE}(-[a-z]+)?[^<]*/${NEW_VERSION_BASE}\1${NEW_SNAPSHOT}/" pom.xml sed -ri "0,/$CURRENT_VERSION_BASE/s/${CURRENT_VERSION_BASE}(-[a-z]+)?[^<]*/${NEW_VERSION_BASE}\1${NEW_SNAPSHOT}/" pom.xml