diff --git a/gcloud-java-pubsub/README.md b/gcloud-java-pubsub/README.md
new file mode 100644
index 000000000000..70393a4b7998
--- /dev/null
+++ b/gcloud-java-pubsub/README.md
@@ -0,0 +1,84 @@
+Google Cloud Java Client for Pub/Sub
+====================================
+
+Java idiomatic client for [Google Cloud Pub/Sub] (https://cloud.google.com/pubsub/).
+
+[![Build Status](https://travis-ci.org/GoogleCloudPlatform/gcloud-java.svg?branch=master)](https://travis-ci.org/GoogleCloudPlatform/gcloud-java)
+[![Coverage Status](https://coveralls.io/repos/GoogleCloudPlatform/gcloud-java/badge.svg?branch=master)](https://coveralls.io/r/GoogleCloudPlatform/gcloud-java?branch=master)
+[![Maven](https://img.shields.io/maven-central/v/com.google.gcloud/gcloud-java-pubsub.svg)]( https://img.shields.io/maven-central/v/com.google.gcloud/gcloud-java-pubsub.svg)
+
+- [Homepage] (https://googlecloudplatform.github.io/gcloud-java/)
+- [API Documentation] (http://googlecloudplatform.github.io/gcloud-java/apidocs)
+
+> Note: This client is a work-in-progress, and may occasionally
+> make backwards-incompatible changes.
+
+Quickstart
+----------
+Add this to your pom.xml file
+```xml
+
+ com.google.gcloud
+ gcloud-java-pubsub
+ 0.0.10
+
+```
+
+Example Application
+-------------------
+TODO
+
+Authentication
+--------------
+
+See the [Authentication](https://github.com/GoogleCloudPlatform/gcloud-java#authentication) section in the base directory's README.
+
+About Google Cloud Pub/Sub
+--------------------------
+
+[Google Cloud Pub/Sub][cloud-pubsub] is designed to provide reliable,
+many-to-many, asynchronous messaging between applications. Publisher
+applications can send messages to a ``topic`` and other applications can
+subscribe to that topic to receive the messages. By decoupling senders and
+receivers, Google Cloud Pub/Sub allows developers to communicate between
+independently written applications.
+
+TODO: link to docs on activating Pub/Sub, high-level documentation on
+the API, and code snippet
+
+Java Versions
+-------------
+
+Java 7 or above is required for using this client.
+
+Testing
+-------
+
+TODO
+
+Versioning
+----------
+
+This library follows [Semantic Versioning] (http://semver.org/).
+
+It is currently in major version zero (``0.y.z``), which means that anything
+may change at any time and the public API should not be considered
+stable.
+
+Contributing
+------------
+
+Contributions to this library are always welcome and highly encouraged.
+
+See [CONTRIBUTING] for more information on how to get started.
+
+License
+-------
+
+Apache 2.0 - See [LICENSE] for more information.
+
+
+[CONTRIBUTING]:https://github.com/GoogleCloudPlatform/gcloud-java/blob/master/CONTRIBUTING.md
+[LICENSE]: https://github.com/GoogleCloudPlatform/gcloud-java/blob/master/LICENSE
+
+[cloud-pubsub]: https://cloud.google.com/storage/
diff --git a/gcloud-java-pubsub/baseline/src/main/java/com/google/gcloud/pubsub/spi/v1/PublisherApi.java b/gcloud-java-pubsub/baseline/src/main/java/com/google/gcloud/pubsub/spi/v1/PublisherApi.java
new file mode 100644
index 000000000000..fa6da27a72bd
--- /dev/null
+++ b/gcloud-java-pubsub/baseline/src/main/java/com/google/gcloud/pubsub/spi/v1/PublisherApi.java
@@ -0,0 +1,554 @@
+/*
+ * Copyright 2015 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.
+ */
+
+/*
+ * EDITING INSTRUCTIONS
+ * This file was generated from the file
+ * https://github.com/google/googleapis/blob/master/google/pubsub/v1/pubsub.proto
+ * and updates to that file get reflected here through a refresh process.
+ * For the short term, the refresh process will only be runnable by Google engineers.
+ * Manual additions are allowed because the refresh process performs
+ * a 3-way merge in order to preserve those manual additions. In order to not
+ * break the refresh process, only certain types of modifications are
+ * allowed.
+ *
+ * Allowed modifications - currently these are the only types allowed:
+ * 1. New methods (these should be added to the end of the class)
+ * 2. New imports
+ * 3. Additional documentation between "manual edit" demarcations
+ *
+ * Happy editing!
+ */
+
+package com.google.gcloud.pubsub.spi.v1;
+
+import com.google.api.gax.grpc.ApiCallable;
+import com.google.api.gax.grpc.ApiCallable.BundlableApiCallableInfo;
+import com.google.api.gax.grpc.BundlerFactory;
+import com.google.api.gax.protobuf.PathTemplate;
+import com.google.protobuf.Empty;
+import com.google.pubsub.v1.DeleteTopicRequest;
+import com.google.pubsub.v1.GetTopicRequest;
+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.PublishRequest;
+import com.google.pubsub.v1.PublishResponse;
+import com.google.pubsub.v1.PubsubMessage;
+import com.google.pubsub.v1.Topic;
+import io.grpc.ManagedChannel;
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+// Manually-added imports: add custom (non-generated) imports after this point.
+
+// AUTO-GENERATED DOCUMENTATION AND SERVICE - see instructions at the top of the file for editing.
+/**
+ * Service Description: The service that an application uses to manipulate topics, and to send
+ * messages to a topic.
+ *
+ *
+ *
+ */
+@javax.annotation.Generated("by GAPIC")
+public class PublisherApi implements AutoCloseable {
+ // ========
+ // Members
+ // ========
+
+ private final ManagedChannel channel;
+ private final List closeables = new ArrayList<>();
+
+ private final ApiCallable createTopicCallable;
+ private final ApiCallable publishCallable;
+ private final ApiCallable getTopicCallable;
+ private final ApiCallable listTopicsCallable;
+ private final ApiCallable> listTopicsIterableCallable;
+ private final ApiCallable
+ listTopicSubscriptionsCallable;
+ private final ApiCallable>
+ listTopicSubscriptionsIterableCallable;
+ private final ApiCallable deleteTopicCallable;
+
+ public static class ResourceNames {
+
+ // =======================
+ // ResourceNames Constants
+ // =======================
+
+ /**
+ * A PathTemplate representing the fully-qualified path to represent
+ * a project resource.
+ *
+ *
+ *
+ */
+ private static final PathTemplate PROJECT_PATH_TEMPLATE =
+ PathTemplate.create("projects/{project}");
+
+ /**
+ * A PathTemplate representing the fully-qualified path to represent
+ * a topic resource.
+ *
+ *
+ *
+ */
+ private static final PathTemplate TOPIC_PATH_TEMPLATE =
+ PathTemplate.create("projects/{project}/topics/{topic}");
+
+ private ResourceNames() {}
+
+ // ==============================
+ // Resource Name Helper Functions
+ // ==============================
+
+ /**
+ * Formats a string containing the fully-qualified path to represent
+ * a project resource.
+ *
+ *
+ *
+ */
+ public static final String formatProjectPath(String project) {
+ return PROJECT_PATH_TEMPLATE.instantiate("project", project);
+ }
+
+ /**
+ * Formats a string containing the fully-qualified path to represent
+ * a topic resource.
+ *
+ *
+ *
+ */
+ public static final String formatTopicPath(String project, String topic) {
+ return TOPIC_PATH_TEMPLATE.instantiate("project", project, "topic", topic);
+ }
+
+ /**
+ * Parses the project from the given fully-qualified path which
+ * represents a project resource.
+ *
+ *
+ *
+ */
+ public static final String parseProjectFromProjectPath(String projectPath) {
+ return PROJECT_PATH_TEMPLATE.parse(projectPath).get("project");
+ }
+
+ /**
+ * Parses the project from the given fully-qualified path which
+ * represents a topic resource.
+ *
+ *
+ *
+ */
+ public static final String parseProjectFromTopicPath(String topicPath) {
+ return TOPIC_PATH_TEMPLATE.parse(topicPath).get("project");
+ }
+
+ /**
+ * Parses the topic from the given fully-qualified path which
+ * represents a topic resource.
+ *
+ *
+ *
+ */
+ public static final String parseTopicFromTopicPath(String topicPath) {
+ return TOPIC_PATH_TEMPLATE.parse(topicPath).get("topic");
+ }
+ }
+
+ // ===============
+ // Factory Methods
+ // ===============
+
+ /**
+ * Constructs an instance of PublisherApi with default settings.
+ *
+ *
+ *
+ */
+ public static PublisherApi create() throws IOException {
+ return create(PublisherSettings.create());
+ }
+
+ /**
+ * Constructs an instance of PublisherApi, 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 PublisherApi create(PublisherSettings settings) throws IOException {
+ return new PublisherApi(settings);
+ }
+
+ /**
+ * Constructs an instance of PublisherApi, 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 PublisherApi(PublisherSettings settings) throws IOException {
+ this.channel = settings.getChannel();
+
+ this.createTopicCallable = settings.createTopicMethod().build(settings);
+ BundlableApiCallableInfo bundlablePublish =
+ settings.publishMethod().buildBundlable(settings);
+ this.publishCallable = bundlablePublish.getApiCallable();
+ BundlerFactory publishBundlerFactory =
+ bundlablePublish.getBundlerFactory();
+ if (publishBundlerFactory != null) {
+ this.closeables.add(publishBundlerFactory);
+ }
+ this.getTopicCallable = settings.getTopicMethod().build(settings);
+ this.listTopicsCallable = settings.listTopicsMethod().build(settings);
+ this.listTopicsIterableCallable = settings.listTopicsMethod().buildPageStreaming(settings);
+ this.listTopicSubscriptionsCallable = settings.listTopicSubscriptionsMethod().build(settings);
+ this.listTopicSubscriptionsIterableCallable =
+ settings.listTopicSubscriptionsMethod().buildPageStreaming(settings);
+ this.deleteTopicCallable = settings.deleteTopicMethod().build(settings);
+
+ closeables.add(
+ new Closeable() {
+ @Override
+ public void close() throws IOException {
+ channel.shutdown();
+ }
+ });
+ }
+
+ // =============
+ // Service Calls
+ // =============
+
+ // ----- createTopic -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Creates the given topic with the given name.
+ *
+ *
+ *
+ *
+ * @param name The name of the topic. It must have the format
+ * `"projects/{project}/topics/{topic}"`. `{topic}` must start with a letter,
+ * and contain only letters (`[A-Za-z]`), numbers (`[0-9]`), dashes (`-`),
+ * underscores (`_`), periods (`.`), tildes (`~`), plus (`+`) or percent
+ * signs (`%`). It must be between 3 and 255 characters in length, and it
+ * must not start with `"goog"`.
+ */
+ public Topic createTopic(String name) {
+ Topic request = Topic.newBuilder().setName(name).build();
+
+ return createTopic(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Creates the given topic with the given name.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ private Topic createTopic(Topic request) {
+ return createTopicCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Creates the given topic with the given name.
+ *
+ *
+ *
+ */
+ public ApiCallable createTopicCallable() {
+ return createTopicCallable;
+ }
+
+ // ----- publish -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Adds one or more messages to the topic. Generates `NOT_FOUND` if the topic
+ * does not exist. The message payload must not be empty; it must contain
+ * either a non-empty data field, or at least one attribute.
+ *
+ *
+ *
+ *
+ * @param topic The messages in the request will be published on this topic.
+ * @param messages The messages to publish.
+ */
+ public PublishResponse publish(String topic, List messages) {
+ PublishRequest request =
+ PublishRequest.newBuilder().setTopic(topic).addAllMessages(messages).build();
+
+ return publish(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Adds one or more messages to the topic. Generates `NOT_FOUND` if the topic
+ * does not exist. The message payload must not be empty; it must contain
+ * either a non-empty data field, or at least one attribute.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public PublishResponse publish(PublishRequest request) {
+ return publishCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Adds one or more messages to the topic. Generates `NOT_FOUND` if the topic
+ * does not exist. The message payload must not be empty; it must contain
+ * either a non-empty data field, or at least one attribute.
+ *
+ *
+ *
+ */
+ public ApiCallable publishCallable() {
+ return publishCallable;
+ }
+
+ // ----- getTopic -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Gets the configuration of a topic.
+ *
+ *
+ *
+ *
+ * @param topic The name of the topic to get.
+ */
+ public Topic getTopic(String topic) {
+ GetTopicRequest request = GetTopicRequest.newBuilder().setTopic(topic).build();
+
+ return getTopic(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Gets the configuration of a topic.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ private Topic getTopic(GetTopicRequest request) {
+ return getTopicCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Gets the configuration of a topic.
+ *
+ *
+ *
+ */
+ public ApiCallable getTopicCallable() {
+ return getTopicCallable;
+ }
+
+ // ----- listTopics -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching topics.
+ *
+ *
+ *
+ */
+ public Iterable listTopics(String project) {
+ ListTopicsRequest request = ListTopicsRequest.newBuilder().setProject(project).build();
+ return listTopics(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching topics.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public Iterable listTopics(ListTopicsRequest request) {
+ return listTopicsIterableCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching topics.
+ *
+ *
+ *
+ */
+ public ApiCallable> listTopicsIterableCallable() {
+ return listTopicsIterableCallable;
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching topics.
+ *
+ *
+ *
+ */
+ public ApiCallable listTopicsCallable() {
+ return listTopicsCallable;
+ }
+
+ // ----- listTopicSubscriptions -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists the name of the subscriptions for this topic.
+ *
+ *
+ *
+ */
+ public Iterable listTopicSubscriptions(String topic) {
+ ListTopicSubscriptionsRequest request =
+ ListTopicSubscriptionsRequest.newBuilder().setTopic(topic).build();
+ return listTopicSubscriptions(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists the name of the subscriptions for this topic.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public Iterable listTopicSubscriptions(ListTopicSubscriptionsRequest request) {
+ return listTopicSubscriptionsIterableCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists the name of the subscriptions for this topic.
+ *
+ *
+ *
+ */
+ public ApiCallable>
+ listTopicSubscriptionsIterableCallable() {
+ return listTopicSubscriptionsIterableCallable;
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists the name of the subscriptions for this topic.
+ *
+ *
+ *
+ */
+ public ApiCallable
+ listTopicSubscriptionsCallable() {
+ return listTopicSubscriptionsCallable;
+ }
+
+ // ----- deleteTopic -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Deletes the topic with the given name. Generates `NOT_FOUND` if the topic
+ * does not exist. After a topic is deleted, a new topic may be created with
+ * the same name; this is an entirely new topic with none of the old
+ * configuration or subscriptions. Existing subscriptions to this topic are
+ * not deleted, but their `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ *
+ * @param topic Name of the topic to delete.
+ */
+ public void deleteTopic(String topic) {
+ DeleteTopicRequest request = DeleteTopicRequest.newBuilder().setTopic(topic).build();
+
+ deleteTopic(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Deletes the topic with the given name. Generates `NOT_FOUND` if the topic
+ * does not exist. After a topic is deleted, a new topic may be created with
+ * the same name; this is an entirely new topic with none of the old
+ * configuration or subscriptions. Existing subscriptions to this topic are
+ * not deleted, but their `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ private void deleteTopic(DeleteTopicRequest request) {
+ deleteTopicCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Deletes the topic with the given name. Generates `NOT_FOUND` if the topic
+ * does not exist. After a topic is deleted, a new topic may be created with
+ * the same name; this is an entirely new topic with none of the old
+ * configuration or subscriptions. Existing subscriptions to this topic are
+ * not deleted, but their `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ */
+ public ApiCallable deleteTopicCallable() {
+ return deleteTopicCallable;
+ }
+
+ // ========
+ // Cleanup
+ // ========
+
+ /**
+ * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately
+ * cancelled.
+ *
+ *
+ *
+ */
+ @Override
+ public void close() throws Exception {
+ for (AutoCloseable closeable : closeables) {
+ closeable.close();
+ }
+ }
+
+ // ========
+ // Manually-added methods: add custom (non-generated) methods after this point.
+ // ========
+
+}
diff --git a/gcloud-java-pubsub/baseline/src/main/java/com/google/gcloud/pubsub/spi/v1/PublisherSettings.java b/gcloud-java-pubsub/baseline/src/main/java/com/google/gcloud/pubsub/spi/v1/PublisherSettings.java
new file mode 100644
index 000000000000..11566404546f
--- /dev/null
+++ b/gcloud-java-pubsub/baseline/src/main/java/com/google/gcloud/pubsub/spi/v1/PublisherSettings.java
@@ -0,0 +1,411 @@
+/*
+ * Copyright 2015 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.
+ */
+
+/*
+ * EDITING INSTRUCTIONS
+ * This file was generated from the file
+ * https://github.com/google/googleapis/blob/master/google/pubsub/v1/pubsub.proto
+ * and updates to that file get reflected here through a refresh process.
+ * For the short term, the refresh process will only be runnable by Google engineers.
+ * Manual additions are allowed because the refresh process performs
+ * a 3-way merge in order to preserve those manual additions. In order to not
+ * break the refresh process, only certain types of modifications are
+ * allowed.
+ *
+ * Allowed modifications - currently these are the only types allowed:
+ * 1. New methods (these should be added to the end of the class)
+ * 2. New imports
+ * 3. Additional documentation between "manual edit" demarcations
+ *
+ * Happy editing!
+ */
+
+package com.google.gcloud.pubsub.spi.v1;
+
+import com.google.api.gax.core.BackoffParams;
+import com.google.api.gax.core.ConnectionSettings;
+import com.google.api.gax.core.RetryParams;
+import com.google.api.gax.grpc.ApiCallSettings;
+import com.google.api.gax.grpc.ApiCallable.ApiCallableBuilder;
+import com.google.api.gax.grpc.ApiCallable.BundlableApiCallableBuilder;
+import com.google.api.gax.grpc.ApiCallable.PageStreamingApiCallableBuilder;
+import com.google.api.gax.grpc.BundlingDescriptor;
+import com.google.api.gax.grpc.PageStreamingDescriptor;
+import com.google.api.gax.grpc.RequestIssuer;
+import com.google.api.gax.grpc.ServiceApiSettings;
+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.Empty;
+import com.google.pubsub.v1.DeleteTopicRequest;
+import com.google.pubsub.v1.GetTopicRequest;
+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.PublishRequest;
+import com.google.pubsub.v1.PublishResponse;
+import com.google.pubsub.v1.PublisherGrpc;
+import com.google.pubsub.v1.PubsubMessage;
+import com.google.pubsub.v1.Topic;
+import io.grpc.Status;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+// Manually-added imports: add custom (non-generated) imports after this point.
+
+// AUTO-GENERATED DOCUMENTATION AND CLASS - see instructions at the top of the file for editing.
+@javax.annotation.Generated("by GAPIC")
+public class PublisherSettings extends ServiceApiSettings {
+
+ // =========
+ // Constants
+ // =========
+
+ /**
+ * The default address of the service.
+ *
+ *
+ *
+ */
+ public static final String DEFAULT_SERVICE_ADDRESS = "pubsub-experimental.googleapis.com";
+
+ /**
+ * The default port of the service.
+ *
+ *
+ *
+ */
+ public static final int DEFAULT_SERVICE_PORT = 443;
+
+ /**
+ * The default scopes of the service.
+ */
+ public static final ImmutableList DEFAULT_SERVICE_SCOPES =
+ ImmutableList.builder()
+ .add("https://www.googleapis.com/auth/pubsub")
+ .add("https://www.googleapis.com/auth/cloud-platform")
+ .build();
+
+ 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()));
+ RETRYABLE_CODE_DEFINITIONS = definitions.build();
+ }
+
+ private static final ImmutableMap RETRY_PARAM_DEFINITIONS;
+
+ static {
+ ImmutableMap.Builder definitions = ImmutableMap.builder();
+ RetryParams params = null;
+ params =
+ RetryParams.newBuilder()
+ .setRetryBackoff(
+ BackoffParams.newBuilder()
+ .setInitialDelayMillis(100L)
+ .setDelayMultiplier(1.2)
+ .setMaxDelayMillis(1000L)
+ .build())
+ .setTimeoutBackoff(
+ BackoffParams.newBuilder()
+ .setInitialDelayMillis(300L)
+ .setDelayMultiplier(1.3)
+ .setMaxDelayMillis(3000L)
+ .build())
+ .setTotalTimeout(30000L)
+ .build();
+ definitions.put("default", params);
+ RETRY_PARAM_DEFINITIONS = definitions.build();
+ }
+
+ private final MethodBuilders methods;
+
+ private static class MethodBuilders {
+ private final ApiCallableBuilder createTopicMethod;
+ private final BundlableApiCallableBuilder publishMethod;
+ private final ApiCallableBuilder getTopicMethod;
+ private final PageStreamingApiCallableBuilder
+ listTopicsMethod;
+ private final PageStreamingApiCallableBuilder<
+ ListTopicSubscriptionsRequest, ListTopicSubscriptionsResponse, String>
+ listTopicSubscriptionsMethod;
+ private final ApiCallableBuilder deleteTopicMethod;
+ private final ImmutableList extends ApiCallSettings> allMethods;
+
+ public MethodBuilders() {
+ createTopicMethod = new ApiCallableBuilder<>(PublisherGrpc.METHOD_CREATE_TOPIC);
+ createTopicMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ createTopicMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ publishMethod =
+ new BundlableApiCallableBuilder<>(PublisherGrpc.METHOD_PUBLISH, PUBLISH_BUNDLING_DESC);
+ publishMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"));
+ publishMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ getTopicMethod = new ApiCallableBuilder<>(PublisherGrpc.METHOD_GET_TOPIC);
+ getTopicMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ getTopicMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ listTopicsMethod =
+ new PageStreamingApiCallableBuilder<>(
+ PublisherGrpc.METHOD_LIST_TOPICS, LIST_TOPICS_PAGE_STR_DESC);
+ listTopicsMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ listTopicsMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ listTopicSubscriptionsMethod =
+ new PageStreamingApiCallableBuilder<>(
+ PublisherGrpc.METHOD_LIST_TOPIC_SUBSCRIPTIONS,
+ LIST_TOPIC_SUBSCRIPTIONS_PAGE_STR_DESC);
+ listTopicSubscriptionsMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ listTopicSubscriptionsMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ deleteTopicMethod = new ApiCallableBuilder<>(PublisherGrpc.METHOD_DELETE_TOPIC);
+ deleteTopicMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ deleteTopicMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ allMethods =
+ ImmutableList.builder()
+ .add(
+ createTopicMethod,
+ publishMethod,
+ getTopicMethod,
+ listTopicsMethod,
+ listTopicSubscriptionsMethod,
+ deleteTopicMethod)
+ .build();
+ }
+ }
+
+ // ===============
+ // Factory Methods
+ // ===============
+
+ /**
+ * Constructs an instance of PublisherSettings with default settings.
+ *
+ *
+ *
+ */
+ public static PublisherSettings create() {
+ PublisherSettings settings = new PublisherSettings(new MethodBuilders());
+ settings.provideChannelWith(
+ ConnectionSettings.builder()
+ .setServiceAddress(DEFAULT_SERVICE_ADDRESS)
+ .setPort(DEFAULT_SERVICE_PORT)
+ .provideCredentialsWith(DEFAULT_SERVICE_SCOPES)
+ .build());
+ return settings;
+ }
+
+ /**
+ * Constructs an instance of PublisherSettings with default settings. This is protected
+ * so that it easy to make a subclass, but otherwise, the static factory methods should be
+ * preferred.
+ *
+ *
+ *
+ */
+ protected PublisherSettings(MethodBuilders methods) {
+ super(methods.allMethods);
+ this.methods = methods;
+ }
+
+ /**
+ * Returns the builder for the API method createTopic.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder createTopicMethod() {
+ return methods.createTopicMethod;
+ }
+
+ /**
+ * Returns the builder for the API method publish.
+ *
+ *
+ *
+ */
+ public BundlableApiCallableBuilder publishMethod() {
+ return methods.publishMethod;
+ }
+
+ /**
+ * Returns the builder for the API method getTopic.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder getTopicMethod() {
+ return methods.getTopicMethod;
+ }
+
+ /**
+ * Returns the builder for the API method listTopics.
+ *
+ *
+ *
+ */
+ public PageStreamingApiCallableBuilder
+ listTopicsMethod() {
+ return methods.listTopicsMethod;
+ }
+
+ /**
+ * Returns the builder for the API method listTopicSubscriptions.
+ *
+ *
+ *
+ */
+ public PageStreamingApiCallableBuilder<
+ ListTopicSubscriptionsRequest, ListTopicSubscriptionsResponse, String>
+ listTopicSubscriptionsMethod() {
+ return methods.listTopicSubscriptionsMethod;
+ }
+
+ /**
+ * Returns the builder for the API method deleteTopic.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder deleteTopicMethod() {
+ return methods.deleteTopicMethod;
+ }
+
+ private static PageStreamingDescriptor
+ LIST_TOPICS_PAGE_STR_DESC =
+ new PageStreamingDescriptor() {
+ @Override
+ public Object emptyToken() {
+ return "";
+ }
+
+ @Override
+ public ListTopicsRequest injectToken(ListTopicsRequest payload, Object token) {
+ return ListTopicsRequest.newBuilder(payload).setPageToken((String) token).build();
+ }
+
+ @Override
+ public Object extractNextToken(ListTopicsResponse payload) {
+ return payload.getNextPageToken();
+ }
+
+ @Override
+ public Iterable extractResources(ListTopicsResponse payload) {
+ return payload.getTopicsList();
+ }
+ };
+
+ private static PageStreamingDescriptor<
+ ListTopicSubscriptionsRequest, ListTopicSubscriptionsResponse, String>
+ LIST_TOPIC_SUBSCRIPTIONS_PAGE_STR_DESC =
+ new PageStreamingDescriptor<
+ ListTopicSubscriptionsRequest, ListTopicSubscriptionsResponse, String>() {
+ @Override
+ public Object emptyToken() {
+ return "";
+ }
+
+ @Override
+ public ListTopicSubscriptionsRequest injectToken(
+ ListTopicSubscriptionsRequest payload, Object token) {
+ return ListTopicSubscriptionsRequest.newBuilder(payload)
+ .setPageToken((String) token)
+ .build();
+ }
+
+ @Override
+ public Object extractNextToken(ListTopicSubscriptionsResponse payload) {
+ return payload.getNextPageToken();
+ }
+
+ @Override
+ public Iterable extractResources(ListTopicSubscriptionsResponse payload) {
+ return payload.getSubscriptionsList();
+ }
+ };
+
+ private static BundlingDescriptor PUBLISH_BUNDLING_DESC =
+ new BundlingDescriptor() {
+ @Override
+ public String getBundlePartitionKey(PublishRequest request) {
+ return request.getTopic();
+ }
+
+ @Override
+ public PublishRequest mergeRequests(Collection requests) {
+ PublishRequest firstRequest = requests.iterator().next();
+
+ List elements = new ArrayList<>();
+ for (PublishRequest request : requests) {
+ elements.addAll(request.getMessagesList());
+ }
+
+ PublishRequest bundleRequest =
+ PublishRequest.newBuilder()
+ .setTopic(firstRequest.getTopic())
+ .addAllMessages(elements)
+ .build();
+ return bundleRequest;
+ }
+
+ @Override
+ public void splitResponse(
+ PublishResponse bundleResponse,
+ Collection extends RequestIssuer> bundle) {
+ int bundleMessageIndex = 0;
+ for (RequestIssuer responder : bundle) {
+ List subresponseElements = new ArrayList<>();
+ int subresponseCount = responder.getRequest().getMessagesCount();
+ for (int i = 0; i < subresponseCount; i++) {
+ subresponseElements.add(bundleResponse.getMessageIds(bundleMessageIndex));
+ bundleMessageIndex += 1;
+ }
+ PublishResponse response =
+ PublishResponse.newBuilder().addAllMessageIds(subresponseElements).build();
+ responder.setResponse(response);
+ }
+ }
+
+ @Override
+ public void splitException(
+ Throwable throwable,
+ Collection extends RequestIssuer> bundle) {
+ for (RequestIssuer responder : bundle) {
+ responder.setException(throwable);
+ }
+ }
+
+ @Override
+ public long countElements(PublishRequest request) {
+ return request.getMessagesCount();
+ }
+
+ @Override
+ public long countBytes(PublishRequest request) {
+ return request.getSerializedSize();
+ }
+ };
+}
diff --git a/gcloud-java-pubsub/baseline/src/main/java/com/google/gcloud/pubsub/spi/v1/SubscriberApi.java b/gcloud-java-pubsub/baseline/src/main/java/com/google/gcloud/pubsub/spi/v1/SubscriberApi.java
new file mode 100644
index 000000000000..d53dca7f8885
--- /dev/null
+++ b/gcloud-java-pubsub/baseline/src/main/java/com/google/gcloud/pubsub/spi/v1/SubscriberApi.java
@@ -0,0 +1,768 @@
+/*
+ * Copyright 2015 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.
+ */
+
+/*
+ * EDITING INSTRUCTIONS
+ * This file was generated from the file
+ * https://github.com/google/googleapis/blob/master/google/pubsub/v1/pubsub.proto
+ * and updates to that file get reflected here through a refresh process.
+ * For the short term, the refresh process will only be runnable by Google engineers.
+ * Manual additions are allowed because the refresh process performs
+ * a 3-way merge in order to preserve those manual additions. In order to not
+ * break the refresh process, only certain types of modifications are
+ * allowed.
+ *
+ * Allowed modifications - currently these are the only types allowed:
+ * 1. New methods (these should be added to the end of the class)
+ * 2. New imports
+ * 3. Additional documentation between "manual edit" demarcations
+ *
+ * Happy editing!
+ */
+
+package com.google.gcloud.pubsub.spi.v1;
+
+import com.google.api.gax.grpc.ApiCallable;
+import com.google.api.gax.protobuf.PathTemplate;
+import com.google.protobuf.Empty;
+import com.google.pubsub.v1.AcknowledgeRequest;
+import com.google.pubsub.v1.DeleteSubscriptionRequest;
+import com.google.pubsub.v1.GetSubscriptionRequest;
+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.PushConfig;
+import com.google.pubsub.v1.Subscription;
+import io.grpc.ManagedChannel;
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+// Manually-added imports: add custom (non-generated) imports after this point.
+
+// AUTO-GENERATED DOCUMENTATION AND SERVICE - see instructions at the top of the file for editing.
+/**
+ * Service Description: The service that an application uses to manipulate subscriptions and to
+ * consume messages from a subscription via the `Pull` method.
+ *
+ *
+ *
+ */
+@javax.annotation.Generated("by GAPIC")
+public class SubscriberApi implements AutoCloseable {
+ // ========
+ // Members
+ // ========
+
+ private final ManagedChannel channel;
+ private final List closeables = new ArrayList<>();
+
+ private final ApiCallable createSubscriptionCallable;
+ private final ApiCallable getSubscriptionCallable;
+ private final ApiCallable
+ listSubscriptionsCallable;
+ private final ApiCallable>
+ listSubscriptionsIterableCallable;
+ private final ApiCallable deleteSubscriptionCallable;
+ private final ApiCallable modifyAckDeadlineCallable;
+ private final ApiCallable acknowledgeCallable;
+ private final ApiCallable pullCallable;
+ private final ApiCallable modifyPushConfigCallable;
+
+ public static class ResourceNames {
+
+ // =======================
+ // ResourceNames Constants
+ // =======================
+
+ /**
+ * A PathTemplate representing the fully-qualified path to represent
+ * a project resource.
+ *
+ *
+ *
+ */
+ private static final PathTemplate PROJECT_PATH_TEMPLATE =
+ PathTemplate.create("projects/{project}");
+
+ /**
+ * A PathTemplate representing the fully-qualified path to represent
+ * a subscription resource.
+ *
+ *
+ *
+ */
+ private static final PathTemplate SUBSCRIPTION_PATH_TEMPLATE =
+ PathTemplate.create("projects/{project}/subscriptions/{subscription}");
+
+ private ResourceNames() {}
+
+ // ==============================
+ // Resource Name Helper Functions
+ // ==============================
+
+ /**
+ * Formats a string containing the fully-qualified path to represent
+ * a project resource.
+ *
+ *
+ *
+ */
+ public static final String formatProjectPath(String project) {
+ return PROJECT_PATH_TEMPLATE.instantiate("project", project);
+ }
+
+ /**
+ * Formats a string containing the fully-qualified path to represent
+ * a subscription resource.
+ *
+ *
+ *
+ */
+ public static final String formatSubscriptionPath(String project, String subscription) {
+ return SUBSCRIPTION_PATH_TEMPLATE.instantiate(
+ "project", project, "subscription", subscription);
+ }
+
+ /**
+ * Parses the project from the given fully-qualified path which
+ * represents a project resource.
+ *
+ *
+ *
+ */
+ public static final String parseProjectFromProjectPath(String projectPath) {
+ return PROJECT_PATH_TEMPLATE.parse(projectPath).get("project");
+ }
+
+ /**
+ * Parses the project from the given fully-qualified path which
+ * represents a subscription resource.
+ *
+ *
+ *
+ */
+ public static final String parseProjectFromSubscriptionPath(String subscriptionPath) {
+ return SUBSCRIPTION_PATH_TEMPLATE.parse(subscriptionPath).get("project");
+ }
+
+ /**
+ * Parses the subscription from the given fully-qualified path which
+ * represents a subscription resource.
+ *
+ *
+ *
+ */
+ public static final String parseSubscriptionFromSubscriptionPath(String subscriptionPath) {
+ return SUBSCRIPTION_PATH_TEMPLATE.parse(subscriptionPath).get("subscription");
+ }
+ }
+
+ // ===============
+ // Factory Methods
+ // ===============
+
+ /**
+ * Constructs an instance of SubscriberApi with default settings.
+ *
+ *
+ *
+ */
+ public static SubscriberApi create() throws IOException {
+ return create(SubscriberSettings.create());
+ }
+
+ /**
+ * Constructs an instance of SubscriberApi, 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 SubscriberApi create(SubscriberSettings settings) throws IOException {
+ return new SubscriberApi(settings);
+ }
+
+ /**
+ * Constructs an instance of SubscriberApi, 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 SubscriberApi(SubscriberSettings settings) throws IOException {
+ this.channel = settings.getChannel();
+
+ this.createSubscriptionCallable = settings.createSubscriptionMethod().build(settings);
+ this.getSubscriptionCallable = settings.getSubscriptionMethod().build(settings);
+ this.listSubscriptionsCallable = settings.listSubscriptionsMethod().build(settings);
+ this.listSubscriptionsIterableCallable =
+ settings.listSubscriptionsMethod().buildPageStreaming(settings);
+ this.deleteSubscriptionCallable = settings.deleteSubscriptionMethod().build(settings);
+ this.modifyAckDeadlineCallable = settings.modifyAckDeadlineMethod().build(settings);
+ this.acknowledgeCallable = settings.acknowledgeMethod().build(settings);
+ this.pullCallable = settings.pullMethod().build(settings);
+ this.modifyPushConfigCallable = settings.modifyPushConfigMethod().build(settings);
+
+ closeables.add(
+ new Closeable() {
+ @Override
+ public void close() throws IOException {
+ channel.shutdown();
+ }
+ });
+ }
+
+ // =============
+ // Service Calls
+ // =============
+
+ // ----- createSubscription -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Creates a subscription to a given topic for a given subscriber.
+ * If the subscription already exists, generates `ALREADY_EXISTS`.
+ * If the corresponding topic doesn't exist, generates `NOT_FOUND`.
+ *
+ * If the name is not provided in the request, the server will assign a random
+ * name for this subscription on the same project as the topic.
+ *
+ *
+ *
+ *
+ * @param name The name of the subscription. It must have the format
+ * `"projects/{project}/subscriptions/{subscription}"`. `{subscription}` must
+ * start with a letter, and contain only letters (`[A-Za-z]`), numbers
+ * (`[0-9]`), dashes (`-`), underscores (`_`), periods (`.`), tildes (`~`),
+ * plus (`+`) or percent signs (`%`). It must be between 3 and 255 characters
+ * in length, and it must not start with `"goog"`.
+ * @param topic The name of the topic from which this subscription is receiving messages.
+ * @param pushConfig If push delivery is used with this subscription, this field is
+ * used to configure it. An empty `pushConfig` signifies that the subscriber
+ * will pull and ack messages using API methods.
+ * @param ackDeadlineSeconds This value is the maximum time after a subscriber receives a message
+ * before the subscriber should acknowledge the message. After message
+ * delivery but before the ack deadline expires and before the message is
+ * acknowledged, it is an outstanding message and will not be delivered
+ * again during that time (on a best-effort basis).
+ *
+ * For pull subscriptions, this value is used as the initial value for the ack
+ * deadline. To override this value for a given message, call
+ * `ModifyAckDeadline` with the corresponding `ack_id` if using
+ * pull.
+ *
+ * For push delivery, this value is also used to set the request timeout for
+ * the call to the push endpoint.
+ *
+ * If the subscriber never acknowledges the message, the Pub/Sub
+ * system will eventually redeliver the message.
+ *
+ * If this parameter is not set, the default value of 10 seconds is used.
+ */
+ public Subscription createSubscription(
+ String name, String topic, PushConfig pushConfig, int ackDeadlineSeconds) {
+ Subscription request =
+ Subscription.newBuilder()
+ .setName(name)
+ .setTopic(topic)
+ .setPushConfig(pushConfig)
+ .setAckDeadlineSeconds(ackDeadlineSeconds)
+ .build();
+
+ return createSubscription(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Creates a subscription to a given topic for a given subscriber.
+ * If the subscription already exists, generates `ALREADY_EXISTS`.
+ * If the corresponding topic doesn't exist, generates `NOT_FOUND`.
+ *
+ * If the name is not provided in the request, the server will assign a random
+ * name for this subscription on the same project as the topic.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public Subscription createSubscription(Subscription request) {
+ return createSubscriptionCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Creates a subscription to a given topic for a given subscriber.
+ * If the subscription already exists, generates `ALREADY_EXISTS`.
+ * If the corresponding topic doesn't exist, generates `NOT_FOUND`.
+ *
+ * If the name is not provided in the request, the server will assign a random
+ * name for this subscription on the same project as the topic.
+ *
+ *
+ *
+ */
+ public ApiCallable createSubscriptionCallable() {
+ return createSubscriptionCallable;
+ }
+
+ // ----- getSubscription -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Gets the configuration details of a subscription.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ *
+ * @param subscription The name of the subscription to get.
+ */
+ public Subscription getSubscription(String subscription) {
+ GetSubscriptionRequest request =
+ GetSubscriptionRequest.newBuilder().setSubscription(subscription).build();
+
+ return getSubscription(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Gets the configuration details of a subscription.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ private Subscription getSubscription(GetSubscriptionRequest request) {
+ return getSubscriptionCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Gets the configuration details of a subscription.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ */
+ public ApiCallable getSubscriptionCallable() {
+ return getSubscriptionCallable;
+ }
+
+ // ----- listSubscriptions -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching subscriptions.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ */
+ public Iterable listSubscriptions(String project) {
+ ListSubscriptionsRequest request =
+ ListSubscriptionsRequest.newBuilder().setProject(project).build();
+ return listSubscriptions(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching subscriptions.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public Iterable listSubscriptions(ListSubscriptionsRequest request) {
+ return listSubscriptionsIterableCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching subscriptions.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ */
+ public ApiCallable>
+ listSubscriptionsIterableCallable() {
+ return listSubscriptionsIterableCallable;
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching subscriptions.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ */
+ public ApiCallable
+ listSubscriptionsCallable() {
+ return listSubscriptionsCallable;
+ }
+
+ // ----- deleteSubscription -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Deletes an existing subscription. All pending messages in the subscription
+ * are immediately dropped. Calls to `Pull` after deletion will generate
+ * `NOT_FOUND`. After a subscription is deleted, a new one may be created with
+ * the same name, but the new one has no association with the old
+ * subscription, or its topic unless the same topic is specified.
+ *
+ *
+ *
+ *
+ * @param subscription The subscription to delete.
+ */
+ public void deleteSubscription(String subscription) {
+ DeleteSubscriptionRequest request =
+ DeleteSubscriptionRequest.newBuilder().setSubscription(subscription).build();
+
+ deleteSubscription(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Deletes an existing subscription. All pending messages in the subscription
+ * are immediately dropped. Calls to `Pull` after deletion will generate
+ * `NOT_FOUND`. After a subscription is deleted, a new one may be created with
+ * the same name, but the new one has no association with the old
+ * subscription, or its topic unless the same topic is specified.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ private void deleteSubscription(DeleteSubscriptionRequest request) {
+ deleteSubscriptionCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Deletes an existing subscription. All pending messages in the subscription
+ * are immediately dropped. Calls to `Pull` after deletion will generate
+ * `NOT_FOUND`. After a subscription is deleted, a new one may be created with
+ * the same name, but the new one has no association with the old
+ * subscription, or its topic unless the same topic is specified.
+ *
+ *
+ *
+ */
+ public ApiCallable deleteSubscriptionCallable() {
+ return deleteSubscriptionCallable;
+ }
+
+ // ----- modifyAckDeadline -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Modifies the ack deadline for a specific message. This method is useful
+ * to indicate that more time is needed to process a message by the
+ * subscriber, or to make the message available for redelivery if the
+ * processing was interrupted.
+ *
+ *
+ *
+ *
+ * @param subscription The name of the subscription.
+ * @param ackIds List of acknowledgment IDs.
+ * @param ackDeadlineSeconds The new ack deadline with respect to the time this request was sent to
+ * the Pub/Sub system. Must be >= 0. For example, if the value is 10, the new
+ * ack deadline will expire 10 seconds after the `ModifyAckDeadline` call
+ * was made. Specifying zero may immediately make the message available for
+ * another pull request.
+ */
+ public void modifyAckDeadline(String subscription, List ackIds, int ackDeadlineSeconds) {
+ ModifyAckDeadlineRequest request =
+ ModifyAckDeadlineRequest.newBuilder()
+ .setSubscription(subscription)
+ .addAllAckIds(ackIds)
+ .setAckDeadlineSeconds(ackDeadlineSeconds)
+ .build();
+
+ modifyAckDeadline(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Modifies the ack deadline for a specific message. This method is useful
+ * to indicate that more time is needed to process a message by the
+ * subscriber, or to make the message available for redelivery if the
+ * processing was interrupted.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public void modifyAckDeadline(ModifyAckDeadlineRequest request) {
+ modifyAckDeadlineCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Modifies the ack deadline for a specific message. This method is useful
+ * to indicate that more time is needed to process a message by the
+ * subscriber, or to make the message available for redelivery if the
+ * processing was interrupted.
+ *
+ *
+ *
+ */
+ public ApiCallable modifyAckDeadlineCallable() {
+ return modifyAckDeadlineCallable;
+ }
+
+ // ----- acknowledge -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Acknowledges the messages associated with the `ack_ids` in the
+ * `AcknowledgeRequest`. The Pub/Sub system can remove the relevant messages
+ * from the subscription.
+ *
+ * Acknowledging a message whose ack deadline has expired may succeed,
+ * but such a message may be redelivered later. Acknowledging a message more
+ * than once will not result in an error.
+ *
+ *
+ *
+ *
+ * @param subscription The subscription whose message is being acknowledged.
+ * @param ackIds The acknowledgment ID for the messages being acknowledged that was returned
+ * by the Pub/Sub system in the `Pull` response. Must not be empty.
+ */
+ public void acknowledge(String subscription, List ackIds) {
+ AcknowledgeRequest request =
+ AcknowledgeRequest.newBuilder().setSubscription(subscription).addAllAckIds(ackIds).build();
+
+ acknowledge(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Acknowledges the messages associated with the `ack_ids` in the
+ * `AcknowledgeRequest`. The Pub/Sub system can remove the relevant messages
+ * from the subscription.
+ *
+ * Acknowledging a message whose ack deadline has expired may succeed,
+ * but such a message may be redelivered later. Acknowledging a message more
+ * than once will not result in an error.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public void acknowledge(AcknowledgeRequest request) {
+ acknowledgeCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Acknowledges the messages associated with the `ack_ids` in the
+ * `AcknowledgeRequest`. The Pub/Sub system can remove the relevant messages
+ * from the subscription.
+ *
+ * Acknowledging a message whose ack deadline has expired may succeed,
+ * but such a message may be redelivered later. Acknowledging a message more
+ * than once will not result in an error.
+ *
+ *
+ *
+ */
+ public ApiCallable acknowledgeCallable() {
+ return acknowledgeCallable;
+ }
+
+ // ----- pull -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Pulls messages from the server. Returns an empty list if there are no
+ * messages available in the backlog. The server may generate `UNAVAILABLE` if
+ * there are too many concurrent pull requests pending for the given
+ * subscription.
+ *
+ *
+ *
+ *
+ * @param subscription The subscription from which messages should be pulled.
+ * @param returnImmediately If this is specified as true the system will respond immediately even if
+ * it is not able to return a message in the `Pull` response. Otherwise the
+ * system is allowed to wait until at least one message is available rather
+ * than returning no messages.
+ * @param maxMessages The maximum number of messages returned for this request. The Pub/Sub
+ * system may return fewer than the number specified.
+ */
+ public PullResponse pull(String subscription, boolean returnImmediately, int maxMessages) {
+ PullRequest request =
+ PullRequest.newBuilder()
+ .setSubscription(subscription)
+ .setReturnImmediately(returnImmediately)
+ .setMaxMessages(maxMessages)
+ .build();
+
+ return pull(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Pulls messages from the server. Returns an empty list if there are no
+ * messages available in the backlog. The server may generate `UNAVAILABLE` if
+ * there are too many concurrent pull requests pending for the given
+ * subscription.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public PullResponse pull(PullRequest request) {
+ return pullCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Pulls messages from the server. Returns an empty list if there are no
+ * messages available in the backlog. The server may generate `UNAVAILABLE` if
+ * there are too many concurrent pull requests pending for the given
+ * subscription.
+ *
+ *
+ *
+ */
+ public ApiCallable pullCallable() {
+ return pullCallable;
+ }
+
+ // ----- modifyPushConfig -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Modifies the `PushConfig` for a specified subscription.
+ *
+ * This may be used to change a push subscription to a pull one (signified by
+ * an empty `PushConfig`) or vice versa, or change the endpoint URL and other
+ * attributes of a push subscription. Messages will accumulate for delivery
+ * continuously through the call regardless of changes to the `PushConfig`.
+ *
+ *
+ *
+ *
+ * @param subscription The name of the subscription.
+ * @param pushConfig The push configuration for future deliveries.
+ *
+ * An empty `pushConfig` indicates that the Pub/Sub system should
+ * stop pushing messages from the given subscription and allow
+ * messages to be pulled and acknowledged - effectively pausing
+ * the subscription if `Pull` is not called.
+ */
+ public void modifyPushConfig(String subscription, PushConfig pushConfig) {
+ ModifyPushConfigRequest request =
+ ModifyPushConfigRequest.newBuilder()
+ .setSubscription(subscription)
+ .setPushConfig(pushConfig)
+ .build();
+
+ modifyPushConfig(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Modifies the `PushConfig` for a specified subscription.
+ *
+ * This may be used to change a push subscription to a pull one (signified by
+ * an empty `PushConfig`) or vice versa, or change the endpoint URL and other
+ * attributes of a push subscription. Messages will accumulate for delivery
+ * continuously through the call regardless of changes to the `PushConfig`.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public void modifyPushConfig(ModifyPushConfigRequest request) {
+ modifyPushConfigCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Modifies the `PushConfig` for a specified subscription.
+ *
+ * This may be used to change a push subscription to a pull one (signified by
+ * an empty `PushConfig`) or vice versa, or change the endpoint URL and other
+ * attributes of a push subscription. Messages will accumulate for delivery
+ * continuously through the call regardless of changes to the `PushConfig`.
+ *
+ *
+ *
+ */
+ public ApiCallable modifyPushConfigCallable() {
+ return modifyPushConfigCallable;
+ }
+
+ // ========
+ // Cleanup
+ // ========
+
+ /**
+ * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately
+ * cancelled.
+ *
+ *
+ *
+ */
+ @Override
+ public void close() throws Exception {
+ for (AutoCloseable closeable : closeables) {
+ closeable.close();
+ }
+ }
+
+ // ========
+ // Manually-added methods: add custom (non-generated) methods after this point.
+ // ========
+
+}
diff --git a/gcloud-java-pubsub/baseline/src/main/java/com/google/gcloud/pubsub/spi/v1/SubscriberSettings.java b/gcloud-java-pubsub/baseline/src/main/java/com/google/gcloud/pubsub/spi/v1/SubscriberSettings.java
new file mode 100644
index 000000000000..d9da44aa81f7
--- /dev/null
+++ b/gcloud-java-pubsub/baseline/src/main/java/com/google/gcloud/pubsub/spi/v1/SubscriberSettings.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright 2015 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.
+ */
+
+/*
+ * EDITING INSTRUCTIONS
+ * This file was generated from the file
+ * https://github.com/google/googleapis/blob/master/google/pubsub/v1/pubsub.proto
+ * and updates to that file get reflected here through a refresh process.
+ * For the short term, the refresh process will only be runnable by Google engineers.
+ * Manual additions are allowed because the refresh process performs
+ * a 3-way merge in order to preserve those manual additions. In order to not
+ * break the refresh process, only certain types of modifications are
+ * allowed.
+ *
+ * Allowed modifications - currently these are the only types allowed:
+ * 1. New methods (these should be added to the end of the class)
+ * 2. New imports
+ * 3. Additional documentation between "manual edit" demarcations
+ *
+ * Happy editing!
+ */
+
+package com.google.gcloud.pubsub.spi.v1;
+
+import com.google.api.gax.core.BackoffParams;
+import com.google.api.gax.core.ConnectionSettings;
+import com.google.api.gax.core.RetryParams;
+import com.google.api.gax.grpc.ApiCallSettings;
+import com.google.api.gax.grpc.ApiCallable.ApiCallableBuilder;
+import com.google.api.gax.grpc.ApiCallable.PageStreamingApiCallableBuilder;
+import com.google.api.gax.grpc.PageStreamingDescriptor;
+import com.google.api.gax.grpc.ServiceApiSettings;
+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.Empty;
+import com.google.pubsub.v1.AcknowledgeRequest;
+import com.google.pubsub.v1.DeleteSubscriptionRequest;
+import com.google.pubsub.v1.GetSubscriptionRequest;
+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.SubscriberGrpc;
+import com.google.pubsub.v1.Subscription;
+import io.grpc.Status;
+
+// Manually-added imports: add custom (non-generated) imports after this point.
+
+// AUTO-GENERATED DOCUMENTATION AND CLASS - see instructions at the top of the file for editing.
+@javax.annotation.Generated("by GAPIC")
+public class SubscriberSettings extends ServiceApiSettings {
+
+ // =========
+ // Constants
+ // =========
+
+ /**
+ * The default address of the service.
+ *
+ *
+ *
+ */
+ public static final String DEFAULT_SERVICE_ADDRESS = "pubsub-experimental.googleapis.com";
+
+ /**
+ * The default port of the service.
+ *
+ *
+ *
+ */
+ public static final int DEFAULT_SERVICE_PORT = 443;
+
+ /**
+ * The default scopes of the service.
+ */
+ public static final ImmutableList DEFAULT_SERVICE_SCOPES =
+ ImmutableList.builder()
+ .add("https://www.googleapis.com/auth/pubsub")
+ .add("https://www.googleapis.com/auth/cloud-platform")
+ .build();
+
+ 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()));
+ RETRYABLE_CODE_DEFINITIONS = definitions.build();
+ }
+
+ private static final ImmutableMap RETRY_PARAM_DEFINITIONS;
+
+ static {
+ ImmutableMap.Builder definitions = ImmutableMap.builder();
+ RetryParams params = null;
+ params =
+ RetryParams.newBuilder()
+ .setRetryBackoff(
+ BackoffParams.newBuilder()
+ .setInitialDelayMillis(100L)
+ .setDelayMultiplier(1.2)
+ .setMaxDelayMillis(1000L)
+ .build())
+ .setTimeoutBackoff(
+ BackoffParams.newBuilder()
+ .setInitialDelayMillis(300L)
+ .setDelayMultiplier(1.3)
+ .setMaxDelayMillis(3000L)
+ .build())
+ .setTotalTimeout(30000L)
+ .build();
+ definitions.put("default", params);
+ RETRY_PARAM_DEFINITIONS = definitions.build();
+ }
+
+ private final MethodBuilders methods;
+
+ private static class MethodBuilders {
+ private final ApiCallableBuilder createSubscriptionMethod;
+ private final ApiCallableBuilder getSubscriptionMethod;
+ private final PageStreamingApiCallableBuilder<
+ ListSubscriptionsRequest, ListSubscriptionsResponse, Subscription>
+ listSubscriptionsMethod;
+ private final ApiCallableBuilder deleteSubscriptionMethod;
+ private final ApiCallableBuilder modifyAckDeadlineMethod;
+ private final ApiCallableBuilder acknowledgeMethod;
+ private final ApiCallableBuilder pullMethod;
+ private final ApiCallableBuilder modifyPushConfigMethod;
+ private final ImmutableList extends ApiCallSettings> allMethods;
+
+ public MethodBuilders() {
+ createSubscriptionMethod =
+ new ApiCallableBuilder<>(SubscriberGrpc.METHOD_CREATE_SUBSCRIPTION);
+ createSubscriptionMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"));
+ createSubscriptionMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ getSubscriptionMethod = new ApiCallableBuilder<>(SubscriberGrpc.METHOD_GET_SUBSCRIPTION);
+ getSubscriptionMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ getSubscriptionMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ listSubscriptionsMethod =
+ new PageStreamingApiCallableBuilder<>(
+ SubscriberGrpc.METHOD_LIST_SUBSCRIPTIONS, LIST_SUBSCRIPTIONS_PAGE_STR_DESC);
+ listSubscriptionsMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ listSubscriptionsMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ deleteSubscriptionMethod =
+ new ApiCallableBuilder<>(SubscriberGrpc.METHOD_DELETE_SUBSCRIPTION);
+ deleteSubscriptionMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ deleteSubscriptionMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ modifyAckDeadlineMethod = new ApiCallableBuilder<>(SubscriberGrpc.METHOD_MODIFY_ACK_DEADLINE);
+ modifyAckDeadlineMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"));
+ modifyAckDeadlineMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ acknowledgeMethod = new ApiCallableBuilder<>(SubscriberGrpc.METHOD_ACKNOWLEDGE);
+ acknowledgeMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"));
+ acknowledgeMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ pullMethod = new ApiCallableBuilder<>(SubscriberGrpc.METHOD_PULL);
+ pullMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"));
+ pullMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ modifyPushConfigMethod = new ApiCallableBuilder<>(SubscriberGrpc.METHOD_MODIFY_PUSH_CONFIG);
+ modifyPushConfigMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"));
+ modifyPushConfigMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ allMethods =
+ ImmutableList.builder()
+ .add(
+ createSubscriptionMethod,
+ getSubscriptionMethod,
+ listSubscriptionsMethod,
+ deleteSubscriptionMethod,
+ modifyAckDeadlineMethod,
+ acknowledgeMethod,
+ pullMethod,
+ modifyPushConfigMethod)
+ .build();
+ }
+ }
+
+ // ===============
+ // Factory Methods
+ // ===============
+
+ /**
+ * Constructs an instance of SubscriberSettings with default settings.
+ *
+ *
+ *
+ */
+ public static SubscriberSettings create() {
+ SubscriberSettings settings = new SubscriberSettings(new MethodBuilders());
+ settings.provideChannelWith(
+ ConnectionSettings.builder()
+ .setServiceAddress(DEFAULT_SERVICE_ADDRESS)
+ .setPort(DEFAULT_SERVICE_PORT)
+ .provideCredentialsWith(DEFAULT_SERVICE_SCOPES)
+ .build());
+ return settings;
+ }
+
+ /**
+ * Constructs an instance of SubscriberSettings with default settings. This is protected
+ * so that it easy to make a subclass, but otherwise, the static factory methods should be
+ * preferred.
+ *
+ *
+ *
+ */
+ protected SubscriberSettings(MethodBuilders methods) {
+ super(methods.allMethods);
+ this.methods = methods;
+ }
+
+ /**
+ * Returns the builder for the API method createSubscription.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder createSubscriptionMethod() {
+ return methods.createSubscriptionMethod;
+ }
+
+ /**
+ * Returns the builder for the API method getSubscription.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder getSubscriptionMethod() {
+ return methods.getSubscriptionMethod;
+ }
+
+ /**
+ * Returns the builder for the API method listSubscriptions.
+ *
+ *
+ *
+ */
+ public PageStreamingApiCallableBuilder<
+ ListSubscriptionsRequest, ListSubscriptionsResponse, Subscription>
+ listSubscriptionsMethod() {
+ return methods.listSubscriptionsMethod;
+ }
+
+ /**
+ * Returns the builder for the API method deleteSubscription.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder deleteSubscriptionMethod() {
+ return methods.deleteSubscriptionMethod;
+ }
+
+ /**
+ * Returns the builder for the API method modifyAckDeadline.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder modifyAckDeadlineMethod() {
+ return methods.modifyAckDeadlineMethod;
+ }
+
+ /**
+ * Returns the builder for the API method acknowledge.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder acknowledgeMethod() {
+ return methods.acknowledgeMethod;
+ }
+
+ /**
+ * Returns the builder for the API method pull.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder pullMethod() {
+ return methods.pullMethod;
+ }
+
+ /**
+ * Returns the builder for the API method modifyPushConfig.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder modifyPushConfigMethod() {
+ return methods.modifyPushConfigMethod;
+ }
+
+ private static PageStreamingDescriptor<
+ ListSubscriptionsRequest, ListSubscriptionsResponse, Subscription>
+ LIST_SUBSCRIPTIONS_PAGE_STR_DESC =
+ new PageStreamingDescriptor<
+ ListSubscriptionsRequest, ListSubscriptionsResponse, Subscription>() {
+ @Override
+ public Object emptyToken() {
+ return "";
+ }
+
+ @Override
+ public ListSubscriptionsRequest injectToken(
+ ListSubscriptionsRequest payload, Object token) {
+ return ListSubscriptionsRequest.newBuilder(payload)
+ .setPageToken((String) token)
+ .build();
+ }
+
+ @Override
+ public Object extractNextToken(ListSubscriptionsResponse payload) {
+ return payload.getNextPageToken();
+ }
+
+ @Override
+ public Iterable extractResources(ListSubscriptionsResponse payload) {
+ return payload.getSubscriptionsList();
+ }
+ };
+}
diff --git a/gcloud-java-pubsub/pom.xml b/gcloud-java-pubsub/pom.xml
new file mode 100644
index 000000000000..2bd755f63a8c
--- /dev/null
+++ b/gcloud-java-pubsub/pom.xml
@@ -0,0 +1,94 @@
+
+
+ 4.0.0
+ gcloud-java-pubsub
+ jar
+ GCloud Java Pub/Sub
+
+ Java idiomatic client for Google Cloud Pub/Sub.
+
+
+ com.google.gcloud
+ gcloud-java-pom
+ 0.1.4-SNAPSHOT
+
+
+ gcloud-java-pubsub
+
+
+
+ com.google.api
+ gax
+ 0.0.5
+
+
+ com.google.api.grpc
+ grpc-pubsub-v1
+ 0.0.0
+
+
+ io.grpc
+ grpc-all
+ 0.9.0
+
+
+ com.google.auto.value
+ auto-value
+ 1.1
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+
+
+ doclint-java8-disable
+
+ [1.8,)
+
+
+
+ -Xdoclint:none
+
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 1.9.1
+
+
+ generate-sources
+ add-source
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.10.3
+
+
+ attach-javadocs
+
+ jar
+
+
+ ${javadoc.opts}
+
+
+
+
+
+
+
diff --git a/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/spi/v1/PublisherApi.java b/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/spi/v1/PublisherApi.java
new file mode 100644
index 000000000000..fa6da27a72bd
--- /dev/null
+++ b/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/spi/v1/PublisherApi.java
@@ -0,0 +1,554 @@
+/*
+ * Copyright 2015 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.
+ */
+
+/*
+ * EDITING INSTRUCTIONS
+ * This file was generated from the file
+ * https://github.com/google/googleapis/blob/master/google/pubsub/v1/pubsub.proto
+ * and updates to that file get reflected here through a refresh process.
+ * For the short term, the refresh process will only be runnable by Google engineers.
+ * Manual additions are allowed because the refresh process performs
+ * a 3-way merge in order to preserve those manual additions. In order to not
+ * break the refresh process, only certain types of modifications are
+ * allowed.
+ *
+ * Allowed modifications - currently these are the only types allowed:
+ * 1. New methods (these should be added to the end of the class)
+ * 2. New imports
+ * 3. Additional documentation between "manual edit" demarcations
+ *
+ * Happy editing!
+ */
+
+package com.google.gcloud.pubsub.spi.v1;
+
+import com.google.api.gax.grpc.ApiCallable;
+import com.google.api.gax.grpc.ApiCallable.BundlableApiCallableInfo;
+import com.google.api.gax.grpc.BundlerFactory;
+import com.google.api.gax.protobuf.PathTemplate;
+import com.google.protobuf.Empty;
+import com.google.pubsub.v1.DeleteTopicRequest;
+import com.google.pubsub.v1.GetTopicRequest;
+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.PublishRequest;
+import com.google.pubsub.v1.PublishResponse;
+import com.google.pubsub.v1.PubsubMessage;
+import com.google.pubsub.v1.Topic;
+import io.grpc.ManagedChannel;
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+// Manually-added imports: add custom (non-generated) imports after this point.
+
+// AUTO-GENERATED DOCUMENTATION AND SERVICE - see instructions at the top of the file for editing.
+/**
+ * Service Description: The service that an application uses to manipulate topics, and to send
+ * messages to a topic.
+ *
+ *
+ *
+ */
+@javax.annotation.Generated("by GAPIC")
+public class PublisherApi implements AutoCloseable {
+ // ========
+ // Members
+ // ========
+
+ private final ManagedChannel channel;
+ private final List closeables = new ArrayList<>();
+
+ private final ApiCallable createTopicCallable;
+ private final ApiCallable publishCallable;
+ private final ApiCallable getTopicCallable;
+ private final ApiCallable listTopicsCallable;
+ private final ApiCallable> listTopicsIterableCallable;
+ private final ApiCallable
+ listTopicSubscriptionsCallable;
+ private final ApiCallable>
+ listTopicSubscriptionsIterableCallable;
+ private final ApiCallable deleteTopicCallable;
+
+ public static class ResourceNames {
+
+ // =======================
+ // ResourceNames Constants
+ // =======================
+
+ /**
+ * A PathTemplate representing the fully-qualified path to represent
+ * a project resource.
+ *
+ *
+ *
+ */
+ private static final PathTemplate PROJECT_PATH_TEMPLATE =
+ PathTemplate.create("projects/{project}");
+
+ /**
+ * A PathTemplate representing the fully-qualified path to represent
+ * a topic resource.
+ *
+ *
+ *
+ */
+ private static final PathTemplate TOPIC_PATH_TEMPLATE =
+ PathTemplate.create("projects/{project}/topics/{topic}");
+
+ private ResourceNames() {}
+
+ // ==============================
+ // Resource Name Helper Functions
+ // ==============================
+
+ /**
+ * Formats a string containing the fully-qualified path to represent
+ * a project resource.
+ *
+ *
+ *
+ */
+ public static final String formatProjectPath(String project) {
+ return PROJECT_PATH_TEMPLATE.instantiate("project", project);
+ }
+
+ /**
+ * Formats a string containing the fully-qualified path to represent
+ * a topic resource.
+ *
+ *
+ *
+ */
+ public static final String formatTopicPath(String project, String topic) {
+ return TOPIC_PATH_TEMPLATE.instantiate("project", project, "topic", topic);
+ }
+
+ /**
+ * Parses the project from the given fully-qualified path which
+ * represents a project resource.
+ *
+ *
+ *
+ */
+ public static final String parseProjectFromProjectPath(String projectPath) {
+ return PROJECT_PATH_TEMPLATE.parse(projectPath).get("project");
+ }
+
+ /**
+ * Parses the project from the given fully-qualified path which
+ * represents a topic resource.
+ *
+ *
+ *
+ */
+ public static final String parseProjectFromTopicPath(String topicPath) {
+ return TOPIC_PATH_TEMPLATE.parse(topicPath).get("project");
+ }
+
+ /**
+ * Parses the topic from the given fully-qualified path which
+ * represents a topic resource.
+ *
+ *
+ *
+ */
+ public static final String parseTopicFromTopicPath(String topicPath) {
+ return TOPIC_PATH_TEMPLATE.parse(topicPath).get("topic");
+ }
+ }
+
+ // ===============
+ // Factory Methods
+ // ===============
+
+ /**
+ * Constructs an instance of PublisherApi with default settings.
+ *
+ *
+ *
+ */
+ public static PublisherApi create() throws IOException {
+ return create(PublisherSettings.create());
+ }
+
+ /**
+ * Constructs an instance of PublisherApi, 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 PublisherApi create(PublisherSettings settings) throws IOException {
+ return new PublisherApi(settings);
+ }
+
+ /**
+ * Constructs an instance of PublisherApi, 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 PublisherApi(PublisherSettings settings) throws IOException {
+ this.channel = settings.getChannel();
+
+ this.createTopicCallable = settings.createTopicMethod().build(settings);
+ BundlableApiCallableInfo bundlablePublish =
+ settings.publishMethod().buildBundlable(settings);
+ this.publishCallable = bundlablePublish.getApiCallable();
+ BundlerFactory publishBundlerFactory =
+ bundlablePublish.getBundlerFactory();
+ if (publishBundlerFactory != null) {
+ this.closeables.add(publishBundlerFactory);
+ }
+ this.getTopicCallable = settings.getTopicMethod().build(settings);
+ this.listTopicsCallable = settings.listTopicsMethod().build(settings);
+ this.listTopicsIterableCallable = settings.listTopicsMethod().buildPageStreaming(settings);
+ this.listTopicSubscriptionsCallable = settings.listTopicSubscriptionsMethod().build(settings);
+ this.listTopicSubscriptionsIterableCallable =
+ settings.listTopicSubscriptionsMethod().buildPageStreaming(settings);
+ this.deleteTopicCallable = settings.deleteTopicMethod().build(settings);
+
+ closeables.add(
+ new Closeable() {
+ @Override
+ public void close() throws IOException {
+ channel.shutdown();
+ }
+ });
+ }
+
+ // =============
+ // Service Calls
+ // =============
+
+ // ----- createTopic -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Creates the given topic with the given name.
+ *
+ *
+ *
+ *
+ * @param name The name of the topic. It must have the format
+ * `"projects/{project}/topics/{topic}"`. `{topic}` must start with a letter,
+ * and contain only letters (`[A-Za-z]`), numbers (`[0-9]`), dashes (`-`),
+ * underscores (`_`), periods (`.`), tildes (`~`), plus (`+`) or percent
+ * signs (`%`). It must be between 3 and 255 characters in length, and it
+ * must not start with `"goog"`.
+ */
+ public Topic createTopic(String name) {
+ Topic request = Topic.newBuilder().setName(name).build();
+
+ return createTopic(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Creates the given topic with the given name.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ private Topic createTopic(Topic request) {
+ return createTopicCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Creates the given topic with the given name.
+ *
+ *
+ *
+ */
+ public ApiCallable createTopicCallable() {
+ return createTopicCallable;
+ }
+
+ // ----- publish -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Adds one or more messages to the topic. Generates `NOT_FOUND` if the topic
+ * does not exist. The message payload must not be empty; it must contain
+ * either a non-empty data field, or at least one attribute.
+ *
+ *
+ *
+ *
+ * @param topic The messages in the request will be published on this topic.
+ * @param messages The messages to publish.
+ */
+ public PublishResponse publish(String topic, List messages) {
+ PublishRequest request =
+ PublishRequest.newBuilder().setTopic(topic).addAllMessages(messages).build();
+
+ return publish(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Adds one or more messages to the topic. Generates `NOT_FOUND` if the topic
+ * does not exist. The message payload must not be empty; it must contain
+ * either a non-empty data field, or at least one attribute.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public PublishResponse publish(PublishRequest request) {
+ return publishCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Adds one or more messages to the topic. Generates `NOT_FOUND` if the topic
+ * does not exist. The message payload must not be empty; it must contain
+ * either a non-empty data field, or at least one attribute.
+ *
+ *
+ *
+ */
+ public ApiCallable publishCallable() {
+ return publishCallable;
+ }
+
+ // ----- getTopic -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Gets the configuration of a topic.
+ *
+ *
+ *
+ *
+ * @param topic The name of the topic to get.
+ */
+ public Topic getTopic(String topic) {
+ GetTopicRequest request = GetTopicRequest.newBuilder().setTopic(topic).build();
+
+ return getTopic(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Gets the configuration of a topic.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ private Topic getTopic(GetTopicRequest request) {
+ return getTopicCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Gets the configuration of a topic.
+ *
+ *
+ *
+ */
+ public ApiCallable getTopicCallable() {
+ return getTopicCallable;
+ }
+
+ // ----- listTopics -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching topics.
+ *
+ *
+ *
+ */
+ public Iterable listTopics(String project) {
+ ListTopicsRequest request = ListTopicsRequest.newBuilder().setProject(project).build();
+ return listTopics(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching topics.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public Iterable listTopics(ListTopicsRequest request) {
+ return listTopicsIterableCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching topics.
+ *
+ *
+ *
+ */
+ public ApiCallable> listTopicsIterableCallable() {
+ return listTopicsIterableCallable;
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching topics.
+ *
+ *
+ *
+ */
+ public ApiCallable listTopicsCallable() {
+ return listTopicsCallable;
+ }
+
+ // ----- listTopicSubscriptions -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists the name of the subscriptions for this topic.
+ *
+ *
+ *
+ */
+ public Iterable listTopicSubscriptions(String topic) {
+ ListTopicSubscriptionsRequest request =
+ ListTopicSubscriptionsRequest.newBuilder().setTopic(topic).build();
+ return listTopicSubscriptions(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists the name of the subscriptions for this topic.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public Iterable listTopicSubscriptions(ListTopicSubscriptionsRequest request) {
+ return listTopicSubscriptionsIterableCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists the name of the subscriptions for this topic.
+ *
+ *
+ *
+ */
+ public ApiCallable>
+ listTopicSubscriptionsIterableCallable() {
+ return listTopicSubscriptionsIterableCallable;
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists the name of the subscriptions for this topic.
+ *
+ *
+ *
+ */
+ public ApiCallable
+ listTopicSubscriptionsCallable() {
+ return listTopicSubscriptionsCallable;
+ }
+
+ // ----- deleteTopic -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Deletes the topic with the given name. Generates `NOT_FOUND` if the topic
+ * does not exist. After a topic is deleted, a new topic may be created with
+ * the same name; this is an entirely new topic with none of the old
+ * configuration or subscriptions. Existing subscriptions to this topic are
+ * not deleted, but their `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ *
+ * @param topic Name of the topic to delete.
+ */
+ public void deleteTopic(String topic) {
+ DeleteTopicRequest request = DeleteTopicRequest.newBuilder().setTopic(topic).build();
+
+ deleteTopic(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Deletes the topic with the given name. Generates `NOT_FOUND` if the topic
+ * does not exist. After a topic is deleted, a new topic may be created with
+ * the same name; this is an entirely new topic with none of the old
+ * configuration or subscriptions. Existing subscriptions to this topic are
+ * not deleted, but their `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ private void deleteTopic(DeleteTopicRequest request) {
+ deleteTopicCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Deletes the topic with the given name. Generates `NOT_FOUND` if the topic
+ * does not exist. After a topic is deleted, a new topic may be created with
+ * the same name; this is an entirely new topic with none of the old
+ * configuration or subscriptions. Existing subscriptions to this topic are
+ * not deleted, but their `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ */
+ public ApiCallable deleteTopicCallable() {
+ return deleteTopicCallable;
+ }
+
+ // ========
+ // Cleanup
+ // ========
+
+ /**
+ * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately
+ * cancelled.
+ *
+ *
+ *
+ */
+ @Override
+ public void close() throws Exception {
+ for (AutoCloseable closeable : closeables) {
+ closeable.close();
+ }
+ }
+
+ // ========
+ // Manually-added methods: add custom (non-generated) methods after this point.
+ // ========
+
+}
diff --git a/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/spi/v1/PublisherSettings.java b/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/spi/v1/PublisherSettings.java
new file mode 100644
index 000000000000..11566404546f
--- /dev/null
+++ b/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/spi/v1/PublisherSettings.java
@@ -0,0 +1,411 @@
+/*
+ * Copyright 2015 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.
+ */
+
+/*
+ * EDITING INSTRUCTIONS
+ * This file was generated from the file
+ * https://github.com/google/googleapis/blob/master/google/pubsub/v1/pubsub.proto
+ * and updates to that file get reflected here through a refresh process.
+ * For the short term, the refresh process will only be runnable by Google engineers.
+ * Manual additions are allowed because the refresh process performs
+ * a 3-way merge in order to preserve those manual additions. In order to not
+ * break the refresh process, only certain types of modifications are
+ * allowed.
+ *
+ * Allowed modifications - currently these are the only types allowed:
+ * 1. New methods (these should be added to the end of the class)
+ * 2. New imports
+ * 3. Additional documentation between "manual edit" demarcations
+ *
+ * Happy editing!
+ */
+
+package com.google.gcloud.pubsub.spi.v1;
+
+import com.google.api.gax.core.BackoffParams;
+import com.google.api.gax.core.ConnectionSettings;
+import com.google.api.gax.core.RetryParams;
+import com.google.api.gax.grpc.ApiCallSettings;
+import com.google.api.gax.grpc.ApiCallable.ApiCallableBuilder;
+import com.google.api.gax.grpc.ApiCallable.BundlableApiCallableBuilder;
+import com.google.api.gax.grpc.ApiCallable.PageStreamingApiCallableBuilder;
+import com.google.api.gax.grpc.BundlingDescriptor;
+import com.google.api.gax.grpc.PageStreamingDescriptor;
+import com.google.api.gax.grpc.RequestIssuer;
+import com.google.api.gax.grpc.ServiceApiSettings;
+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.Empty;
+import com.google.pubsub.v1.DeleteTopicRequest;
+import com.google.pubsub.v1.GetTopicRequest;
+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.PublishRequest;
+import com.google.pubsub.v1.PublishResponse;
+import com.google.pubsub.v1.PublisherGrpc;
+import com.google.pubsub.v1.PubsubMessage;
+import com.google.pubsub.v1.Topic;
+import io.grpc.Status;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+// Manually-added imports: add custom (non-generated) imports after this point.
+
+// AUTO-GENERATED DOCUMENTATION AND CLASS - see instructions at the top of the file for editing.
+@javax.annotation.Generated("by GAPIC")
+public class PublisherSettings extends ServiceApiSettings {
+
+ // =========
+ // Constants
+ // =========
+
+ /**
+ * The default address of the service.
+ *
+ *
+ *
+ */
+ public static final String DEFAULT_SERVICE_ADDRESS = "pubsub-experimental.googleapis.com";
+
+ /**
+ * The default port of the service.
+ *
+ *
+ *
+ */
+ public static final int DEFAULT_SERVICE_PORT = 443;
+
+ /**
+ * The default scopes of the service.
+ */
+ public static final ImmutableList DEFAULT_SERVICE_SCOPES =
+ ImmutableList.builder()
+ .add("https://www.googleapis.com/auth/pubsub")
+ .add("https://www.googleapis.com/auth/cloud-platform")
+ .build();
+
+ 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()));
+ RETRYABLE_CODE_DEFINITIONS = definitions.build();
+ }
+
+ private static final ImmutableMap RETRY_PARAM_DEFINITIONS;
+
+ static {
+ ImmutableMap.Builder definitions = ImmutableMap.builder();
+ RetryParams params = null;
+ params =
+ RetryParams.newBuilder()
+ .setRetryBackoff(
+ BackoffParams.newBuilder()
+ .setInitialDelayMillis(100L)
+ .setDelayMultiplier(1.2)
+ .setMaxDelayMillis(1000L)
+ .build())
+ .setTimeoutBackoff(
+ BackoffParams.newBuilder()
+ .setInitialDelayMillis(300L)
+ .setDelayMultiplier(1.3)
+ .setMaxDelayMillis(3000L)
+ .build())
+ .setTotalTimeout(30000L)
+ .build();
+ definitions.put("default", params);
+ RETRY_PARAM_DEFINITIONS = definitions.build();
+ }
+
+ private final MethodBuilders methods;
+
+ private static class MethodBuilders {
+ private final ApiCallableBuilder createTopicMethod;
+ private final BundlableApiCallableBuilder publishMethod;
+ private final ApiCallableBuilder getTopicMethod;
+ private final PageStreamingApiCallableBuilder
+ listTopicsMethod;
+ private final PageStreamingApiCallableBuilder<
+ ListTopicSubscriptionsRequest, ListTopicSubscriptionsResponse, String>
+ listTopicSubscriptionsMethod;
+ private final ApiCallableBuilder deleteTopicMethod;
+ private final ImmutableList extends ApiCallSettings> allMethods;
+
+ public MethodBuilders() {
+ createTopicMethod = new ApiCallableBuilder<>(PublisherGrpc.METHOD_CREATE_TOPIC);
+ createTopicMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ createTopicMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ publishMethod =
+ new BundlableApiCallableBuilder<>(PublisherGrpc.METHOD_PUBLISH, PUBLISH_BUNDLING_DESC);
+ publishMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"));
+ publishMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ getTopicMethod = new ApiCallableBuilder<>(PublisherGrpc.METHOD_GET_TOPIC);
+ getTopicMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ getTopicMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ listTopicsMethod =
+ new PageStreamingApiCallableBuilder<>(
+ PublisherGrpc.METHOD_LIST_TOPICS, LIST_TOPICS_PAGE_STR_DESC);
+ listTopicsMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ listTopicsMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ listTopicSubscriptionsMethod =
+ new PageStreamingApiCallableBuilder<>(
+ PublisherGrpc.METHOD_LIST_TOPIC_SUBSCRIPTIONS,
+ LIST_TOPIC_SUBSCRIPTIONS_PAGE_STR_DESC);
+ listTopicSubscriptionsMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ listTopicSubscriptionsMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ deleteTopicMethod = new ApiCallableBuilder<>(PublisherGrpc.METHOD_DELETE_TOPIC);
+ deleteTopicMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ deleteTopicMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ allMethods =
+ ImmutableList.builder()
+ .add(
+ createTopicMethod,
+ publishMethod,
+ getTopicMethod,
+ listTopicsMethod,
+ listTopicSubscriptionsMethod,
+ deleteTopicMethod)
+ .build();
+ }
+ }
+
+ // ===============
+ // Factory Methods
+ // ===============
+
+ /**
+ * Constructs an instance of PublisherSettings with default settings.
+ *
+ *
+ *
+ */
+ public static PublisherSettings create() {
+ PublisherSettings settings = new PublisherSettings(new MethodBuilders());
+ settings.provideChannelWith(
+ ConnectionSettings.builder()
+ .setServiceAddress(DEFAULT_SERVICE_ADDRESS)
+ .setPort(DEFAULT_SERVICE_PORT)
+ .provideCredentialsWith(DEFAULT_SERVICE_SCOPES)
+ .build());
+ return settings;
+ }
+
+ /**
+ * Constructs an instance of PublisherSettings with default settings. This is protected
+ * so that it easy to make a subclass, but otherwise, the static factory methods should be
+ * preferred.
+ *
+ *
+ *
+ */
+ protected PublisherSettings(MethodBuilders methods) {
+ super(methods.allMethods);
+ this.methods = methods;
+ }
+
+ /**
+ * Returns the builder for the API method createTopic.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder createTopicMethod() {
+ return methods.createTopicMethod;
+ }
+
+ /**
+ * Returns the builder for the API method publish.
+ *
+ *
+ *
+ */
+ public BundlableApiCallableBuilder publishMethod() {
+ return methods.publishMethod;
+ }
+
+ /**
+ * Returns the builder for the API method getTopic.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder getTopicMethod() {
+ return methods.getTopicMethod;
+ }
+
+ /**
+ * Returns the builder for the API method listTopics.
+ *
+ *
+ *
+ */
+ public PageStreamingApiCallableBuilder
+ listTopicsMethod() {
+ return methods.listTopicsMethod;
+ }
+
+ /**
+ * Returns the builder for the API method listTopicSubscriptions.
+ *
+ *
+ *
+ */
+ public PageStreamingApiCallableBuilder<
+ ListTopicSubscriptionsRequest, ListTopicSubscriptionsResponse, String>
+ listTopicSubscriptionsMethod() {
+ return methods.listTopicSubscriptionsMethod;
+ }
+
+ /**
+ * Returns the builder for the API method deleteTopic.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder deleteTopicMethod() {
+ return methods.deleteTopicMethod;
+ }
+
+ private static PageStreamingDescriptor
+ LIST_TOPICS_PAGE_STR_DESC =
+ new PageStreamingDescriptor() {
+ @Override
+ public Object emptyToken() {
+ return "";
+ }
+
+ @Override
+ public ListTopicsRequest injectToken(ListTopicsRequest payload, Object token) {
+ return ListTopicsRequest.newBuilder(payload).setPageToken((String) token).build();
+ }
+
+ @Override
+ public Object extractNextToken(ListTopicsResponse payload) {
+ return payload.getNextPageToken();
+ }
+
+ @Override
+ public Iterable extractResources(ListTopicsResponse payload) {
+ return payload.getTopicsList();
+ }
+ };
+
+ private static PageStreamingDescriptor<
+ ListTopicSubscriptionsRequest, ListTopicSubscriptionsResponse, String>
+ LIST_TOPIC_SUBSCRIPTIONS_PAGE_STR_DESC =
+ new PageStreamingDescriptor<
+ ListTopicSubscriptionsRequest, ListTopicSubscriptionsResponse, String>() {
+ @Override
+ public Object emptyToken() {
+ return "";
+ }
+
+ @Override
+ public ListTopicSubscriptionsRequest injectToken(
+ ListTopicSubscriptionsRequest payload, Object token) {
+ return ListTopicSubscriptionsRequest.newBuilder(payload)
+ .setPageToken((String) token)
+ .build();
+ }
+
+ @Override
+ public Object extractNextToken(ListTopicSubscriptionsResponse payload) {
+ return payload.getNextPageToken();
+ }
+
+ @Override
+ public Iterable extractResources(ListTopicSubscriptionsResponse payload) {
+ return payload.getSubscriptionsList();
+ }
+ };
+
+ private static BundlingDescriptor PUBLISH_BUNDLING_DESC =
+ new BundlingDescriptor() {
+ @Override
+ public String getBundlePartitionKey(PublishRequest request) {
+ return request.getTopic();
+ }
+
+ @Override
+ public PublishRequest mergeRequests(Collection requests) {
+ PublishRequest firstRequest = requests.iterator().next();
+
+ List elements = new ArrayList<>();
+ for (PublishRequest request : requests) {
+ elements.addAll(request.getMessagesList());
+ }
+
+ PublishRequest bundleRequest =
+ PublishRequest.newBuilder()
+ .setTopic(firstRequest.getTopic())
+ .addAllMessages(elements)
+ .build();
+ return bundleRequest;
+ }
+
+ @Override
+ public void splitResponse(
+ PublishResponse bundleResponse,
+ Collection extends RequestIssuer> bundle) {
+ int bundleMessageIndex = 0;
+ for (RequestIssuer responder : bundle) {
+ List subresponseElements = new ArrayList<>();
+ int subresponseCount = responder.getRequest().getMessagesCount();
+ for (int i = 0; i < subresponseCount; i++) {
+ subresponseElements.add(bundleResponse.getMessageIds(bundleMessageIndex));
+ bundleMessageIndex += 1;
+ }
+ PublishResponse response =
+ PublishResponse.newBuilder().addAllMessageIds(subresponseElements).build();
+ responder.setResponse(response);
+ }
+ }
+
+ @Override
+ public void splitException(
+ Throwable throwable,
+ Collection extends RequestIssuer> bundle) {
+ for (RequestIssuer responder : bundle) {
+ responder.setException(throwable);
+ }
+ }
+
+ @Override
+ public long countElements(PublishRequest request) {
+ return request.getMessagesCount();
+ }
+
+ @Override
+ public long countBytes(PublishRequest request) {
+ return request.getSerializedSize();
+ }
+ };
+}
diff --git a/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/spi/v1/SubscriberApi.java b/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/spi/v1/SubscriberApi.java
new file mode 100644
index 000000000000..d53dca7f8885
--- /dev/null
+++ b/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/spi/v1/SubscriberApi.java
@@ -0,0 +1,768 @@
+/*
+ * Copyright 2015 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.
+ */
+
+/*
+ * EDITING INSTRUCTIONS
+ * This file was generated from the file
+ * https://github.com/google/googleapis/blob/master/google/pubsub/v1/pubsub.proto
+ * and updates to that file get reflected here through a refresh process.
+ * For the short term, the refresh process will only be runnable by Google engineers.
+ * Manual additions are allowed because the refresh process performs
+ * a 3-way merge in order to preserve those manual additions. In order to not
+ * break the refresh process, only certain types of modifications are
+ * allowed.
+ *
+ * Allowed modifications - currently these are the only types allowed:
+ * 1. New methods (these should be added to the end of the class)
+ * 2. New imports
+ * 3. Additional documentation between "manual edit" demarcations
+ *
+ * Happy editing!
+ */
+
+package com.google.gcloud.pubsub.spi.v1;
+
+import com.google.api.gax.grpc.ApiCallable;
+import com.google.api.gax.protobuf.PathTemplate;
+import com.google.protobuf.Empty;
+import com.google.pubsub.v1.AcknowledgeRequest;
+import com.google.pubsub.v1.DeleteSubscriptionRequest;
+import com.google.pubsub.v1.GetSubscriptionRequest;
+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.PushConfig;
+import com.google.pubsub.v1.Subscription;
+import io.grpc.ManagedChannel;
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+// Manually-added imports: add custom (non-generated) imports after this point.
+
+// AUTO-GENERATED DOCUMENTATION AND SERVICE - see instructions at the top of the file for editing.
+/**
+ * Service Description: The service that an application uses to manipulate subscriptions and to
+ * consume messages from a subscription via the `Pull` method.
+ *
+ *
+ *
+ */
+@javax.annotation.Generated("by GAPIC")
+public class SubscriberApi implements AutoCloseable {
+ // ========
+ // Members
+ // ========
+
+ private final ManagedChannel channel;
+ private final List closeables = new ArrayList<>();
+
+ private final ApiCallable createSubscriptionCallable;
+ private final ApiCallable getSubscriptionCallable;
+ private final ApiCallable
+ listSubscriptionsCallable;
+ private final ApiCallable>
+ listSubscriptionsIterableCallable;
+ private final ApiCallable deleteSubscriptionCallable;
+ private final ApiCallable modifyAckDeadlineCallable;
+ private final ApiCallable acknowledgeCallable;
+ private final ApiCallable pullCallable;
+ private final ApiCallable modifyPushConfigCallable;
+
+ public static class ResourceNames {
+
+ // =======================
+ // ResourceNames Constants
+ // =======================
+
+ /**
+ * A PathTemplate representing the fully-qualified path to represent
+ * a project resource.
+ *
+ *
+ *
+ */
+ private static final PathTemplate PROJECT_PATH_TEMPLATE =
+ PathTemplate.create("projects/{project}");
+
+ /**
+ * A PathTemplate representing the fully-qualified path to represent
+ * a subscription resource.
+ *
+ *
+ *
+ */
+ private static final PathTemplate SUBSCRIPTION_PATH_TEMPLATE =
+ PathTemplate.create("projects/{project}/subscriptions/{subscription}");
+
+ private ResourceNames() {}
+
+ // ==============================
+ // Resource Name Helper Functions
+ // ==============================
+
+ /**
+ * Formats a string containing the fully-qualified path to represent
+ * a project resource.
+ *
+ *
+ *
+ */
+ public static final String formatProjectPath(String project) {
+ return PROJECT_PATH_TEMPLATE.instantiate("project", project);
+ }
+
+ /**
+ * Formats a string containing the fully-qualified path to represent
+ * a subscription resource.
+ *
+ *
+ *
+ */
+ public static final String formatSubscriptionPath(String project, String subscription) {
+ return SUBSCRIPTION_PATH_TEMPLATE.instantiate(
+ "project", project, "subscription", subscription);
+ }
+
+ /**
+ * Parses the project from the given fully-qualified path which
+ * represents a project resource.
+ *
+ *
+ *
+ */
+ public static final String parseProjectFromProjectPath(String projectPath) {
+ return PROJECT_PATH_TEMPLATE.parse(projectPath).get("project");
+ }
+
+ /**
+ * Parses the project from the given fully-qualified path which
+ * represents a subscription resource.
+ *
+ *
+ *
+ */
+ public static final String parseProjectFromSubscriptionPath(String subscriptionPath) {
+ return SUBSCRIPTION_PATH_TEMPLATE.parse(subscriptionPath).get("project");
+ }
+
+ /**
+ * Parses the subscription from the given fully-qualified path which
+ * represents a subscription resource.
+ *
+ *
+ *
+ */
+ public static final String parseSubscriptionFromSubscriptionPath(String subscriptionPath) {
+ return SUBSCRIPTION_PATH_TEMPLATE.parse(subscriptionPath).get("subscription");
+ }
+ }
+
+ // ===============
+ // Factory Methods
+ // ===============
+
+ /**
+ * Constructs an instance of SubscriberApi with default settings.
+ *
+ *
+ *
+ */
+ public static SubscriberApi create() throws IOException {
+ return create(SubscriberSettings.create());
+ }
+
+ /**
+ * Constructs an instance of SubscriberApi, 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 SubscriberApi create(SubscriberSettings settings) throws IOException {
+ return new SubscriberApi(settings);
+ }
+
+ /**
+ * Constructs an instance of SubscriberApi, 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 SubscriberApi(SubscriberSettings settings) throws IOException {
+ this.channel = settings.getChannel();
+
+ this.createSubscriptionCallable = settings.createSubscriptionMethod().build(settings);
+ this.getSubscriptionCallable = settings.getSubscriptionMethod().build(settings);
+ this.listSubscriptionsCallable = settings.listSubscriptionsMethod().build(settings);
+ this.listSubscriptionsIterableCallable =
+ settings.listSubscriptionsMethod().buildPageStreaming(settings);
+ this.deleteSubscriptionCallable = settings.deleteSubscriptionMethod().build(settings);
+ this.modifyAckDeadlineCallable = settings.modifyAckDeadlineMethod().build(settings);
+ this.acknowledgeCallable = settings.acknowledgeMethod().build(settings);
+ this.pullCallable = settings.pullMethod().build(settings);
+ this.modifyPushConfigCallable = settings.modifyPushConfigMethod().build(settings);
+
+ closeables.add(
+ new Closeable() {
+ @Override
+ public void close() throws IOException {
+ channel.shutdown();
+ }
+ });
+ }
+
+ // =============
+ // Service Calls
+ // =============
+
+ // ----- createSubscription -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Creates a subscription to a given topic for a given subscriber.
+ * If the subscription already exists, generates `ALREADY_EXISTS`.
+ * If the corresponding topic doesn't exist, generates `NOT_FOUND`.
+ *
+ * If the name is not provided in the request, the server will assign a random
+ * name for this subscription on the same project as the topic.
+ *
+ *
+ *
+ *
+ * @param name The name of the subscription. It must have the format
+ * `"projects/{project}/subscriptions/{subscription}"`. `{subscription}` must
+ * start with a letter, and contain only letters (`[A-Za-z]`), numbers
+ * (`[0-9]`), dashes (`-`), underscores (`_`), periods (`.`), tildes (`~`),
+ * plus (`+`) or percent signs (`%`). It must be between 3 and 255 characters
+ * in length, and it must not start with `"goog"`.
+ * @param topic The name of the topic from which this subscription is receiving messages.
+ * @param pushConfig If push delivery is used with this subscription, this field is
+ * used to configure it. An empty `pushConfig` signifies that the subscriber
+ * will pull and ack messages using API methods.
+ * @param ackDeadlineSeconds This value is the maximum time after a subscriber receives a message
+ * before the subscriber should acknowledge the message. After message
+ * delivery but before the ack deadline expires and before the message is
+ * acknowledged, it is an outstanding message and will not be delivered
+ * again during that time (on a best-effort basis).
+ *
+ * For pull subscriptions, this value is used as the initial value for the ack
+ * deadline. To override this value for a given message, call
+ * `ModifyAckDeadline` with the corresponding `ack_id` if using
+ * pull.
+ *
+ * For push delivery, this value is also used to set the request timeout for
+ * the call to the push endpoint.
+ *
+ * If the subscriber never acknowledges the message, the Pub/Sub
+ * system will eventually redeliver the message.
+ *
+ * If this parameter is not set, the default value of 10 seconds is used.
+ */
+ public Subscription createSubscription(
+ String name, String topic, PushConfig pushConfig, int ackDeadlineSeconds) {
+ Subscription request =
+ Subscription.newBuilder()
+ .setName(name)
+ .setTopic(topic)
+ .setPushConfig(pushConfig)
+ .setAckDeadlineSeconds(ackDeadlineSeconds)
+ .build();
+
+ return createSubscription(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Creates a subscription to a given topic for a given subscriber.
+ * If the subscription already exists, generates `ALREADY_EXISTS`.
+ * If the corresponding topic doesn't exist, generates `NOT_FOUND`.
+ *
+ * If the name is not provided in the request, the server will assign a random
+ * name for this subscription on the same project as the topic.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public Subscription createSubscription(Subscription request) {
+ return createSubscriptionCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Creates a subscription to a given topic for a given subscriber.
+ * If the subscription already exists, generates `ALREADY_EXISTS`.
+ * If the corresponding topic doesn't exist, generates `NOT_FOUND`.
+ *
+ * If the name is not provided in the request, the server will assign a random
+ * name for this subscription on the same project as the topic.
+ *
+ *
+ *
+ */
+ public ApiCallable createSubscriptionCallable() {
+ return createSubscriptionCallable;
+ }
+
+ // ----- getSubscription -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Gets the configuration details of a subscription.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ *
+ * @param subscription The name of the subscription to get.
+ */
+ public Subscription getSubscription(String subscription) {
+ GetSubscriptionRequest request =
+ GetSubscriptionRequest.newBuilder().setSubscription(subscription).build();
+
+ return getSubscription(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Gets the configuration details of a subscription.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ private Subscription getSubscription(GetSubscriptionRequest request) {
+ return getSubscriptionCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Gets the configuration details of a subscription.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ */
+ public ApiCallable getSubscriptionCallable() {
+ return getSubscriptionCallable;
+ }
+
+ // ----- listSubscriptions -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching subscriptions.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ */
+ public Iterable listSubscriptions(String project) {
+ ListSubscriptionsRequest request =
+ ListSubscriptionsRequest.newBuilder().setProject(project).build();
+ return listSubscriptions(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching subscriptions.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public Iterable listSubscriptions(ListSubscriptionsRequest request) {
+ return listSubscriptionsIterableCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching subscriptions.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ */
+ public ApiCallable>
+ listSubscriptionsIterableCallable() {
+ return listSubscriptionsIterableCallable;
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Lists matching subscriptions.
+ *
+ * If the topic of a subscription has been deleted, the subscription itself is
+ * not deleted, but the value of the `topic` field is set to `_deleted-topic_`.
+ *
+ *
+ *
+ */
+ public ApiCallable
+ listSubscriptionsCallable() {
+ return listSubscriptionsCallable;
+ }
+
+ // ----- deleteSubscription -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Deletes an existing subscription. All pending messages in the subscription
+ * are immediately dropped. Calls to `Pull` after deletion will generate
+ * `NOT_FOUND`. After a subscription is deleted, a new one may be created with
+ * the same name, but the new one has no association with the old
+ * subscription, or its topic unless the same topic is specified.
+ *
+ *
+ *
+ *
+ * @param subscription The subscription to delete.
+ */
+ public void deleteSubscription(String subscription) {
+ DeleteSubscriptionRequest request =
+ DeleteSubscriptionRequest.newBuilder().setSubscription(subscription).build();
+
+ deleteSubscription(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Deletes an existing subscription. All pending messages in the subscription
+ * are immediately dropped. Calls to `Pull` after deletion will generate
+ * `NOT_FOUND`. After a subscription is deleted, a new one may be created with
+ * the same name, but the new one has no association with the old
+ * subscription, or its topic unless the same topic is specified.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ private void deleteSubscription(DeleteSubscriptionRequest request) {
+ deleteSubscriptionCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Deletes an existing subscription. All pending messages in the subscription
+ * are immediately dropped. Calls to `Pull` after deletion will generate
+ * `NOT_FOUND`. After a subscription is deleted, a new one may be created with
+ * the same name, but the new one has no association with the old
+ * subscription, or its topic unless the same topic is specified.
+ *
+ *
+ *
+ */
+ public ApiCallable deleteSubscriptionCallable() {
+ return deleteSubscriptionCallable;
+ }
+
+ // ----- modifyAckDeadline -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Modifies the ack deadline for a specific message. This method is useful
+ * to indicate that more time is needed to process a message by the
+ * subscriber, or to make the message available for redelivery if the
+ * processing was interrupted.
+ *
+ *
+ *
+ *
+ * @param subscription The name of the subscription.
+ * @param ackIds List of acknowledgment IDs.
+ * @param ackDeadlineSeconds The new ack deadline with respect to the time this request was sent to
+ * the Pub/Sub system. Must be >= 0. For example, if the value is 10, the new
+ * ack deadline will expire 10 seconds after the `ModifyAckDeadline` call
+ * was made. Specifying zero may immediately make the message available for
+ * another pull request.
+ */
+ public void modifyAckDeadline(String subscription, List ackIds, int ackDeadlineSeconds) {
+ ModifyAckDeadlineRequest request =
+ ModifyAckDeadlineRequest.newBuilder()
+ .setSubscription(subscription)
+ .addAllAckIds(ackIds)
+ .setAckDeadlineSeconds(ackDeadlineSeconds)
+ .build();
+
+ modifyAckDeadline(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Modifies the ack deadline for a specific message. This method is useful
+ * to indicate that more time is needed to process a message by the
+ * subscriber, or to make the message available for redelivery if the
+ * processing was interrupted.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public void modifyAckDeadline(ModifyAckDeadlineRequest request) {
+ modifyAckDeadlineCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Modifies the ack deadline for a specific message. This method is useful
+ * to indicate that more time is needed to process a message by the
+ * subscriber, or to make the message available for redelivery if the
+ * processing was interrupted.
+ *
+ *
+ *
+ */
+ public ApiCallable modifyAckDeadlineCallable() {
+ return modifyAckDeadlineCallable;
+ }
+
+ // ----- acknowledge -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Acknowledges the messages associated with the `ack_ids` in the
+ * `AcknowledgeRequest`. The Pub/Sub system can remove the relevant messages
+ * from the subscription.
+ *
+ * Acknowledging a message whose ack deadline has expired may succeed,
+ * but such a message may be redelivered later. Acknowledging a message more
+ * than once will not result in an error.
+ *
+ *
+ *
+ *
+ * @param subscription The subscription whose message is being acknowledged.
+ * @param ackIds The acknowledgment ID for the messages being acknowledged that was returned
+ * by the Pub/Sub system in the `Pull` response. Must not be empty.
+ */
+ public void acknowledge(String subscription, List ackIds) {
+ AcknowledgeRequest request =
+ AcknowledgeRequest.newBuilder().setSubscription(subscription).addAllAckIds(ackIds).build();
+
+ acknowledge(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Acknowledges the messages associated with the `ack_ids` in the
+ * `AcknowledgeRequest`. The Pub/Sub system can remove the relevant messages
+ * from the subscription.
+ *
+ * Acknowledging a message whose ack deadline has expired may succeed,
+ * but such a message may be redelivered later. Acknowledging a message more
+ * than once will not result in an error.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public void acknowledge(AcknowledgeRequest request) {
+ acknowledgeCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Acknowledges the messages associated with the `ack_ids` in the
+ * `AcknowledgeRequest`. The Pub/Sub system can remove the relevant messages
+ * from the subscription.
+ *
+ * Acknowledging a message whose ack deadline has expired may succeed,
+ * but such a message may be redelivered later. Acknowledging a message more
+ * than once will not result in an error.
+ *
+ *
+ *
+ */
+ public ApiCallable acknowledgeCallable() {
+ return acknowledgeCallable;
+ }
+
+ // ----- pull -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Pulls messages from the server. Returns an empty list if there are no
+ * messages available in the backlog. The server may generate `UNAVAILABLE` if
+ * there are too many concurrent pull requests pending for the given
+ * subscription.
+ *
+ *
+ *
+ *
+ * @param subscription The subscription from which messages should be pulled.
+ * @param returnImmediately If this is specified as true the system will respond immediately even if
+ * it is not able to return a message in the `Pull` response. Otherwise the
+ * system is allowed to wait until at least one message is available rather
+ * than returning no messages.
+ * @param maxMessages The maximum number of messages returned for this request. The Pub/Sub
+ * system may return fewer than the number specified.
+ */
+ public PullResponse pull(String subscription, boolean returnImmediately, int maxMessages) {
+ PullRequest request =
+ PullRequest.newBuilder()
+ .setSubscription(subscription)
+ .setReturnImmediately(returnImmediately)
+ .setMaxMessages(maxMessages)
+ .build();
+
+ return pull(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Pulls messages from the server. Returns an empty list if there are no
+ * messages available in the backlog. The server may generate `UNAVAILABLE` if
+ * there are too many concurrent pull requests pending for the given
+ * subscription.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public PullResponse pull(PullRequest request) {
+ return pullCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Pulls messages from the server. Returns an empty list if there are no
+ * messages available in the backlog. The server may generate `UNAVAILABLE` if
+ * there are too many concurrent pull requests pending for the given
+ * subscription.
+ *
+ *
+ *
+ */
+ public ApiCallable pullCallable() {
+ return pullCallable;
+ }
+
+ // ----- modifyPushConfig -----
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Modifies the `PushConfig` for a specified subscription.
+ *
+ * This may be used to change a push subscription to a pull one (signified by
+ * an empty `PushConfig`) or vice versa, or change the endpoint URL and other
+ * attributes of a push subscription. Messages will accumulate for delivery
+ * continuously through the call regardless of changes to the `PushConfig`.
+ *
+ *
+ *
+ *
+ * @param subscription The name of the subscription.
+ * @param pushConfig The push configuration for future deliveries.
+ *
+ * An empty `pushConfig` indicates that the Pub/Sub system should
+ * stop pushing messages from the given subscription and allow
+ * messages to be pulled and acknowledged - effectively pausing
+ * the subscription if `Pull` is not called.
+ */
+ public void modifyPushConfig(String subscription, PushConfig pushConfig) {
+ ModifyPushConfigRequest request =
+ ModifyPushConfigRequest.newBuilder()
+ .setSubscription(subscription)
+ .setPushConfig(pushConfig)
+ .build();
+
+ modifyPushConfig(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Modifies the `PushConfig` for a specified subscription.
+ *
+ * This may be used to change a push subscription to a pull one (signified by
+ * an empty `PushConfig`) or vice versa, or change the endpoint URL and other
+ * attributes of a push subscription. Messages will accumulate for delivery
+ * continuously through the call regardless of changes to the `PushConfig`.
+ *
+ *
+ *
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ */
+ public void modifyPushConfig(ModifyPushConfigRequest request) {
+ modifyPushConfigCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD - see instructions at the top of the file for editing.
+ /**
+ * Modifies the `PushConfig` for a specified subscription.
+ *
+ * This may be used to change a push subscription to a pull one (signified by
+ * an empty `PushConfig`) or vice versa, or change the endpoint URL and other
+ * attributes of a push subscription. Messages will accumulate for delivery
+ * continuously through the call regardless of changes to the `PushConfig`.
+ *
+ *
+ *
+ */
+ public ApiCallable modifyPushConfigCallable() {
+ return modifyPushConfigCallable;
+ }
+
+ // ========
+ // Cleanup
+ // ========
+
+ /**
+ * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately
+ * cancelled.
+ *
+ *
+ *
+ */
+ @Override
+ public void close() throws Exception {
+ for (AutoCloseable closeable : closeables) {
+ closeable.close();
+ }
+ }
+
+ // ========
+ // Manually-added methods: add custom (non-generated) methods after this point.
+ // ========
+
+}
diff --git a/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/spi/v1/SubscriberSettings.java b/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/spi/v1/SubscriberSettings.java
new file mode 100644
index 000000000000..d9da44aa81f7
--- /dev/null
+++ b/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/spi/v1/SubscriberSettings.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright 2015 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.
+ */
+
+/*
+ * EDITING INSTRUCTIONS
+ * This file was generated from the file
+ * https://github.com/google/googleapis/blob/master/google/pubsub/v1/pubsub.proto
+ * and updates to that file get reflected here through a refresh process.
+ * For the short term, the refresh process will only be runnable by Google engineers.
+ * Manual additions are allowed because the refresh process performs
+ * a 3-way merge in order to preserve those manual additions. In order to not
+ * break the refresh process, only certain types of modifications are
+ * allowed.
+ *
+ * Allowed modifications - currently these are the only types allowed:
+ * 1. New methods (these should be added to the end of the class)
+ * 2. New imports
+ * 3. Additional documentation between "manual edit" demarcations
+ *
+ * Happy editing!
+ */
+
+package com.google.gcloud.pubsub.spi.v1;
+
+import com.google.api.gax.core.BackoffParams;
+import com.google.api.gax.core.ConnectionSettings;
+import com.google.api.gax.core.RetryParams;
+import com.google.api.gax.grpc.ApiCallSettings;
+import com.google.api.gax.grpc.ApiCallable.ApiCallableBuilder;
+import com.google.api.gax.grpc.ApiCallable.PageStreamingApiCallableBuilder;
+import com.google.api.gax.grpc.PageStreamingDescriptor;
+import com.google.api.gax.grpc.ServiceApiSettings;
+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.Empty;
+import com.google.pubsub.v1.AcknowledgeRequest;
+import com.google.pubsub.v1.DeleteSubscriptionRequest;
+import com.google.pubsub.v1.GetSubscriptionRequest;
+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.SubscriberGrpc;
+import com.google.pubsub.v1.Subscription;
+import io.grpc.Status;
+
+// Manually-added imports: add custom (non-generated) imports after this point.
+
+// AUTO-GENERATED DOCUMENTATION AND CLASS - see instructions at the top of the file for editing.
+@javax.annotation.Generated("by GAPIC")
+public class SubscriberSettings extends ServiceApiSettings {
+
+ // =========
+ // Constants
+ // =========
+
+ /**
+ * The default address of the service.
+ *
+ *
+ *
+ */
+ public static final String DEFAULT_SERVICE_ADDRESS = "pubsub-experimental.googleapis.com";
+
+ /**
+ * The default port of the service.
+ *
+ *
+ *
+ */
+ public static final int DEFAULT_SERVICE_PORT = 443;
+
+ /**
+ * The default scopes of the service.
+ */
+ public static final ImmutableList DEFAULT_SERVICE_SCOPES =
+ ImmutableList.builder()
+ .add("https://www.googleapis.com/auth/pubsub")
+ .add("https://www.googleapis.com/auth/cloud-platform")
+ .build();
+
+ 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()));
+ RETRYABLE_CODE_DEFINITIONS = definitions.build();
+ }
+
+ private static final ImmutableMap RETRY_PARAM_DEFINITIONS;
+
+ static {
+ ImmutableMap.Builder definitions = ImmutableMap.builder();
+ RetryParams params = null;
+ params =
+ RetryParams.newBuilder()
+ .setRetryBackoff(
+ BackoffParams.newBuilder()
+ .setInitialDelayMillis(100L)
+ .setDelayMultiplier(1.2)
+ .setMaxDelayMillis(1000L)
+ .build())
+ .setTimeoutBackoff(
+ BackoffParams.newBuilder()
+ .setInitialDelayMillis(300L)
+ .setDelayMultiplier(1.3)
+ .setMaxDelayMillis(3000L)
+ .build())
+ .setTotalTimeout(30000L)
+ .build();
+ definitions.put("default", params);
+ RETRY_PARAM_DEFINITIONS = definitions.build();
+ }
+
+ private final MethodBuilders methods;
+
+ private static class MethodBuilders {
+ private final ApiCallableBuilder createSubscriptionMethod;
+ private final ApiCallableBuilder getSubscriptionMethod;
+ private final PageStreamingApiCallableBuilder<
+ ListSubscriptionsRequest, ListSubscriptionsResponse, Subscription>
+ listSubscriptionsMethod;
+ private final ApiCallableBuilder deleteSubscriptionMethod;
+ private final ApiCallableBuilder modifyAckDeadlineMethod;
+ private final ApiCallableBuilder acknowledgeMethod;
+ private final ApiCallableBuilder pullMethod;
+ private final ApiCallableBuilder modifyPushConfigMethod;
+ private final ImmutableList extends ApiCallSettings> allMethods;
+
+ public MethodBuilders() {
+ createSubscriptionMethod =
+ new ApiCallableBuilder<>(SubscriberGrpc.METHOD_CREATE_SUBSCRIPTION);
+ createSubscriptionMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"));
+ createSubscriptionMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ getSubscriptionMethod = new ApiCallableBuilder<>(SubscriberGrpc.METHOD_GET_SUBSCRIPTION);
+ getSubscriptionMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ getSubscriptionMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ listSubscriptionsMethod =
+ new PageStreamingApiCallableBuilder<>(
+ SubscriberGrpc.METHOD_LIST_SUBSCRIPTIONS, LIST_SUBSCRIPTIONS_PAGE_STR_DESC);
+ listSubscriptionsMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ listSubscriptionsMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ deleteSubscriptionMethod =
+ new ApiCallableBuilder<>(SubscriberGrpc.METHOD_DELETE_SUBSCRIPTION);
+ deleteSubscriptionMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"));
+ deleteSubscriptionMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ modifyAckDeadlineMethod = new ApiCallableBuilder<>(SubscriberGrpc.METHOD_MODIFY_ACK_DEADLINE);
+ modifyAckDeadlineMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"));
+ modifyAckDeadlineMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ acknowledgeMethod = new ApiCallableBuilder<>(SubscriberGrpc.METHOD_ACKNOWLEDGE);
+ acknowledgeMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"));
+ acknowledgeMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ pullMethod = new ApiCallableBuilder<>(SubscriberGrpc.METHOD_PULL);
+ pullMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"));
+ pullMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ modifyPushConfigMethod = new ApiCallableBuilder<>(SubscriberGrpc.METHOD_MODIFY_PUSH_CONFIG);
+ modifyPushConfigMethod.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"));
+ modifyPushConfigMethod.setRetryParams(RETRY_PARAM_DEFINITIONS.get("default"));
+
+ allMethods =
+ ImmutableList.builder()
+ .add(
+ createSubscriptionMethod,
+ getSubscriptionMethod,
+ listSubscriptionsMethod,
+ deleteSubscriptionMethod,
+ modifyAckDeadlineMethod,
+ acknowledgeMethod,
+ pullMethod,
+ modifyPushConfigMethod)
+ .build();
+ }
+ }
+
+ // ===============
+ // Factory Methods
+ // ===============
+
+ /**
+ * Constructs an instance of SubscriberSettings with default settings.
+ *
+ *
+ *
+ */
+ public static SubscriberSettings create() {
+ SubscriberSettings settings = new SubscriberSettings(new MethodBuilders());
+ settings.provideChannelWith(
+ ConnectionSettings.builder()
+ .setServiceAddress(DEFAULT_SERVICE_ADDRESS)
+ .setPort(DEFAULT_SERVICE_PORT)
+ .provideCredentialsWith(DEFAULT_SERVICE_SCOPES)
+ .build());
+ return settings;
+ }
+
+ /**
+ * Constructs an instance of SubscriberSettings with default settings. This is protected
+ * so that it easy to make a subclass, but otherwise, the static factory methods should be
+ * preferred.
+ *
+ *
+ *
+ */
+ protected SubscriberSettings(MethodBuilders methods) {
+ super(methods.allMethods);
+ this.methods = methods;
+ }
+
+ /**
+ * Returns the builder for the API method createSubscription.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder createSubscriptionMethod() {
+ return methods.createSubscriptionMethod;
+ }
+
+ /**
+ * Returns the builder for the API method getSubscription.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder getSubscriptionMethod() {
+ return methods.getSubscriptionMethod;
+ }
+
+ /**
+ * Returns the builder for the API method listSubscriptions.
+ *
+ *
+ *
+ */
+ public PageStreamingApiCallableBuilder<
+ ListSubscriptionsRequest, ListSubscriptionsResponse, Subscription>
+ listSubscriptionsMethod() {
+ return methods.listSubscriptionsMethod;
+ }
+
+ /**
+ * Returns the builder for the API method deleteSubscription.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder deleteSubscriptionMethod() {
+ return methods.deleteSubscriptionMethod;
+ }
+
+ /**
+ * Returns the builder for the API method modifyAckDeadline.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder modifyAckDeadlineMethod() {
+ return methods.modifyAckDeadlineMethod;
+ }
+
+ /**
+ * Returns the builder for the API method acknowledge.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder acknowledgeMethod() {
+ return methods.acknowledgeMethod;
+ }
+
+ /**
+ * Returns the builder for the API method pull.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder pullMethod() {
+ return methods.pullMethod;
+ }
+
+ /**
+ * Returns the builder for the API method modifyPushConfig.
+ *
+ *
+ *
+ */
+ public ApiCallableBuilder modifyPushConfigMethod() {
+ return methods.modifyPushConfigMethod;
+ }
+
+ private static PageStreamingDescriptor<
+ ListSubscriptionsRequest, ListSubscriptionsResponse, Subscription>
+ LIST_SUBSCRIPTIONS_PAGE_STR_DESC =
+ new PageStreamingDescriptor<
+ ListSubscriptionsRequest, ListSubscriptionsResponse, Subscription>() {
+ @Override
+ public Object emptyToken() {
+ return "";
+ }
+
+ @Override
+ public ListSubscriptionsRequest injectToken(
+ ListSubscriptionsRequest payload, Object token) {
+ return ListSubscriptionsRequest.newBuilder(payload)
+ .setPageToken((String) token)
+ .build();
+ }
+
+ @Override
+ public Object extractNextToken(ListSubscriptionsResponse payload) {
+ return payload.getNextPageToken();
+ }
+
+ @Override
+ public Iterable extractResources(ListSubscriptionsResponse payload) {
+ return payload.getSubscriptionsList();
+ }
+ };
+}
diff --git a/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/testing/LocalPubsubHelper.java b/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/testing/LocalPubsubHelper.java
new file mode 100644
index 000000000000..76de1a6d3cc7
--- /dev/null
+++ b/gcloud-java-pubsub/src/main/java/com/google/gcloud/pubsub/testing/LocalPubsubHelper.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2015 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.gcloud.pubsub.testing;
+
+import com.google.api.gax.testing.DownloadableEmulatorRunner;
+import com.google.api.gax.testing.GCloudEmulatorRunner;
+import com.google.api.gax.testing.LocalServiceHelper;
+
+import io.grpc.ManagedChannel;
+import io.grpc.netty.NegotiationType;
+import io.grpc.netty.NettyChannelBuilder;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A class that runs a Pubsub emulator instance for use in tests.
+ */
+public class LocalPubsubHelper {
+ private final LocalServiceHelper serviceHelper;
+ private final List gcloudCommand;
+ private final URL emulatorUrl;
+
+ // Local server settings
+ private static final int DEFAULT_PORT = 8080;
+ private static final String DEFAULT_HOST = "localhost";
+
+ // GCloud emulator settings
+ private static final String GCLOUD_CMD_TEXT = "gcloud beta emulators pubsub start --host-port";
+ private static final String VERSION_PREFIX = "pubsub-emulator";
+ private static final String MIN_VERSION = "2016.01.13";
+
+ // Downloadable emulator settings
+ private static final String FILENAME = "pubsub-emulator-20160113-2.zip";
+ private static final String BIN_NAME = "pubsub-emulator/bin/cloud-pubsub-fake";
+ private static final String MD5_CHECKSUM = "20943e9defa300f2de101568459c133d";
+
+ /**
+ * Constructs a new LocalPubsubHelper. The method start() must
+ * be called before it is used.
+ * @throws MalformedURLException
+ */
+ public LocalPubsubHelper() throws MalformedURLException {
+ gcloudCommand = new ArrayList<>(Arrays.asList(GCLOUD_CMD_TEXT.split(" ")));
+ gcloudCommand.add(DEFAULT_HOST);
+ emulatorUrl = new URL("http://storage.googleapis.com/pubsub/tools/" + FILENAME);
+ GCloudEmulatorRunner gcloudRunner =
+ new GCloudEmulatorRunner(gcloudCommand, VERSION_PREFIX, MIN_VERSION);
+ DownloadableEmulatorRunner downloadRunner =
+ new DownloadableEmulatorRunner(Arrays.asList(BIN_NAME), emulatorUrl, MD5_CHECKSUM);
+ serviceHelper =
+ new LocalServiceHelper(Arrays.asList(gcloudRunner, downloadRunner), DEFAULT_PORT);
+ }
+
+ /**
+ * Start the local pubsub emulator through gcloud, download the zip file if user does not have
+ * gcloud installed.
+ * @throws InterruptedException
+ * @throws IOException
+ */
+ public void start() throws IOException, InterruptedException {
+ String blockUntilOutput = Integer.toString(DEFAULT_PORT);
+ serviceHelper.start(blockUntilOutput);
+ }
+
+ /**
+ * Reset the internal state of the emulator.
+ * @throws InterruptedException
+ * @throws IOException
+ */
+ public void reset() throws IOException, InterruptedException {
+ this.serviceHelper.sendPostRequest("/reset");
+ }
+
+ /**
+ * Quit the local emulator and related local service.
+ * @throws InterruptedException
+ * @throws IOException
+ */
+ public void stop() throws IOException, InterruptedException {
+ this.serviceHelper.sendPostRequest("/shutdown");
+ this.serviceHelper.stop();
+ }
+
+ /**
+ * Creates a channel for making requests to the in-memory service.
+ */
+ public ManagedChannel createChannel() {
+ return NettyChannelBuilder.forAddress(DEFAULT_HOST, DEFAULT_PORT)
+ .negotiationType(NegotiationType.PLAINTEXT)
+ .build();
+ }
+}
diff --git a/gcloud-java-pubsub/src/test/java/com/google/gcloud/pubsub/spi/v1/PublisherApiTest.java b/gcloud-java-pubsub/src/test/java/com/google/gcloud/pubsub/spi/v1/PublisherApiTest.java
new file mode 100644
index 000000000000..c25ca51ee713
--- /dev/null
+++ b/gcloud-java-pubsub/src/test/java/com/google/gcloud/pubsub/spi/v1/PublisherApiTest.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2015 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.gcloud.pubsub.spi.v1;
+
+import com.google.api.gax.core.BackoffParams;
+import com.google.api.gax.core.RetryParams;
+import com.google.api.gax.grpc.BundlingSettings;
+import com.google.gcloud.pubsub.testing.LocalPubsubHelper;
+import com.google.protobuf.ByteString;
+import com.google.pubsub.v1.PubsubMessage;
+import com.google.pubsub.v1.PullResponse;
+import com.google.pubsub.v1.PushConfig;
+import com.google.pubsub.v1.Topic;
+
+import io.grpc.ManagedChannel;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.joda.time.Duration;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class PublisherApiTest {
+ private static LocalPubsubHelper pubsubHelper;
+ private PublisherApi publisherApi;
+ private PublisherApi bundledPublisherApi;
+ private SubscriberApi subscriberApi;
+
+ @BeforeClass
+ public static void startServer() throws IOException, InterruptedException {
+ pubsubHelper = new LocalPubsubHelper();
+ pubsubHelper.start();
+ }
+
+ @AfterClass
+ public static void stopServer() throws IOException, InterruptedException {
+ pubsubHelper.stop();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ ManagedChannel channel = pubsubHelper.createChannel();
+
+ RetryParams retryParams =
+ RetryParams.newBuilder()
+ .setRetryBackoff(
+ BackoffParams.newBuilder()
+ .setInitialDelayMillis(1000L)
+ .setDelayMultiplier(1.2)
+ .setMaxDelayMillis(10000L)
+ .build())
+ .setTimeoutBackoff(
+ BackoffParams.newBuilder()
+ .setInitialDelayMillis(3000L)
+ .setDelayMultiplier(1.3)
+ .setMaxDelayMillis(30000L)
+ .build())
+ .setTotalTimeout(30000L)
+ .build();
+
+ PublisherSettings publisherSettings = PublisherSettings.create();
+ publisherSettings.setRetryParamsOnAllMethods(retryParams);
+ publisherSettings.provideChannelWith(channel);
+ publisherApi = PublisherApi.create(publisherSettings);
+
+ BundlingSettings bundlingSettings =
+ BundlingSettings.newBuilder()
+ .setElementCountThreshold(10)
+ .setDelayThreshold(Duration.standardSeconds(30))
+ .build();
+
+ PublisherSettings bundledPublisherSettings = PublisherSettings.create();
+ bundledPublisherSettings.setRetryParamsOnAllMethods(retryParams);
+ bundledPublisherSettings.provideChannelWith(channel);
+ bundledPublisherSettings.publishMethod().setBundlingSettings(bundlingSettings);
+ bundledPublisherApi = PublisherApi.create(bundledPublisherSettings);
+
+ SubscriberSettings subscriberSettings = SubscriberSettings.create();
+ subscriberSettings.setRetryParamsOnAllMethods(retryParams);
+ subscriberSettings.provideChannelWith(channel);
+ subscriberApi = SubscriberApi.create(subscriberSettings);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (publisherApi != null) {
+ publisherApi.close();
+ }
+ if (subscriberApi != null) {
+ subscriberApi.close();
+ }
+ if (bundledPublisherApi != null) {
+ bundledPublisherApi.close();
+ }
+ pubsubHelper.reset();
+ }
+
+ @Test
+ public void testCreateTopic() throws Exception {
+ String topicName = PublisherApi.ResourceNames.formatTopicPath("my-project", "my-topic");
+ Topic result = publisherApi.createTopic(topicName);
+ Assert.assertEquals(topicName, result.getName());
+ }
+
+ @Test
+ public void testPublish() throws Exception {
+ String topicName = PublisherApi.ResourceNames.formatTopicPath("my-project", "publish-topic");
+ publisherApi.createTopic(topicName);
+
+ String subscriberName =
+ SubscriberApi.ResourceNames.formatSubscriptionPath("my-project", "my-subscribe");
+ PushConfig config = PushConfig.getDefaultInstance();
+ subscriberApi.createSubscription(subscriberName, topicName, config, 5);
+
+ PubsubMessage msg =
+ PubsubMessage.newBuilder().setData(ByteString.copyFromUtf8("pubsub-message")).build();
+ publisherApi.publish(topicName, Collections.singletonList(msg));
+
+ PullResponse response = subscriberApi.pull(subscriberName, true, 100);
+ Assert.assertEquals(1, response.getReceivedMessagesCount());
+ Assert.assertEquals(
+ "pubsub-message", response.getReceivedMessages(0).getMessage().getData().toStringUtf8());
+ }
+
+ @Test
+ public void testBundledPublish() throws Exception {
+ String topicName = PublisherApi.ResourceNames.formatTopicPath("my-project", "publish-topic");
+ bundledPublisherApi.createTopic(topicName);
+
+ String subscriberName =
+ SubscriberApi.ResourceNames.formatSubscriptionPath("my-project", "my-subscribe");
+ PushConfig config = PushConfig.getDefaultInstance();
+ subscriberApi.createSubscription(subscriberName, topicName, config, 5);
+
+ PubsubMessage msg =
+ PubsubMessage.newBuilder().setData(ByteString.copyFromUtf8("pubsub-message")).build();
+ // This is a synchronous publish and should trigger the default blockingCallCountThreshold of 1
+ bundledPublisherApi.publish(topicName, Collections.singletonList(msg));
+
+ PullResponse response = subscriberApi.pull(subscriberName, true, 100);
+ Assert.assertEquals(1, response.getReceivedMessagesCount());
+ Assert.assertEquals(
+ "pubsub-message", response.getReceivedMessages(0).getMessage().getData().toStringUtf8());
+ }
+
+ @Test
+ public void testGetTopic() throws Exception {
+ String topicName = PublisherApi.ResourceNames.formatTopicPath("my-project", "fun-topic");
+ publisherApi.createTopic(topicName);
+ Topic result = publisherApi.getTopic(topicName);
+ Assert.assertNotNull(result);
+ Assert.assertEquals(topicName, result.getName());
+ }
+
+ @Test
+ public void testListTopics() throws Exception {
+ String project1 = PublisherApi.ResourceNames.formatProjectPath("project.1");
+ String topicName1 = PublisherApi.ResourceNames.formatTopicPath("project.1", "topic.1");
+ String topicName2 = PublisherApi.ResourceNames.formatTopicPath("project.1", "topic.2");
+ String topicName3 = PublisherApi.ResourceNames.formatTopicPath("project.2", "topic.3");
+ publisherApi.createTopic(topicName1);
+ publisherApi.createTopic(topicName2);
+ publisherApi.createTopic(topicName3);
+ List topics = new ArrayList<>();
+ for (Topic topic : publisherApi.listTopics(project1)) {
+ topics.add(topic);
+ }
+ Assert.assertEquals(2, topics.size());
+ Assert.assertEquals(topicName1, topics.get(0).getName());
+ Assert.assertEquals(topicName2, topics.get(1).getName());
+ }
+
+ @Test
+ public void testDeleteTopic() throws Exception {
+ String project = PublisherApi.ResourceNames.formatProjectPath("project.1");
+ String topicName = PublisherApi.ResourceNames.formatTopicPath("my-project", "fun-topic");
+ publisherApi.createTopic(topicName);
+ publisherApi.deleteTopic(topicName);
+ List topics = new ArrayList<>();
+ for (Topic topic : publisherApi.listTopics(project)) {
+ topics.add(topic);
+ }
+ Assert.assertEquals(0, topics.size());
+ }
+}
diff --git a/pom.xml b/pom.xml
index 0084fd53d74f..3cfa57b45c96 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,6 +99,7 @@
gcloud-java-coregcloud-java-datastoregcloud-java-examples
+ gcloud-java-pubsubgcloud-java-resourcemanagergcloud-java-storage
@@ -144,7 +145,7 @@
org.apache.maven.pluginsmaven-enforcer-plugin
- 1.4
+ 1.4.1enforce-maven
@@ -159,7 +160,7 @@
[1.7,)
-
+
@@ -186,7 +187,7 @@
org.apache.maven.pluginsmaven-failsafe-plugin
- 2.18.1
+ 2.19.1
@@ -218,7 +219,10 @@
maven-compiler-plugin
- 3.2
+
+
+
+ 3.11.7
@@ -313,12 +317,12 @@
org.apache.maven.pluginsmaven-checkstyle-plugin
- 2.16
+ 2.17com.puppycrawl.toolscheckstyle
- 6.8.1
+ 6.15
@@ -337,7 +341,7 @@
org.apache.maven.pluginsmaven-project-info-reports-plugin
- 2.8
+ 2.8.1
@@ -394,12 +398,12 @@
org.apache.maven.pluginsmaven-surefire-report-plugin
- 2.18.1
+ 2.19.1org.apache.maven.pluginsmaven-checkstyle-plugin
- 2.16
+ 2.17checkstyle.xmlfalse