/* * Copyright 2016 The gRPC Authors * * 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 io.grpc; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.MoreObjects; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.annotation.Nullable; /** * Descriptor for a service. * * @since 1.0.0 */ public final class ServiceDescriptor { private final String name; private final Collection> methods; private final Object schemaDescriptor; /** * Constructs a new Service Descriptor. Users are encouraged to use {@link #newBuilder} * instead. * * @param name The name of the service * @param methods The methods that are part of the service * @since 1.0.0 */ public ServiceDescriptor(String name, MethodDescriptor... methods) { this(name, Arrays.asList(methods)); } /** * Constructs a new Service Descriptor. Users are encouraged to use {@link #newBuilder} * instead. * * @param name The name of the service * @param methods The methods that are part of the service * @since 1.0.0 */ public ServiceDescriptor(String name, Collection> methods) { this(newBuilder(name).addAllMethods(checkNotNull(methods, "methods"))); } private ServiceDescriptor(Builder b) { this.name = b.name; validateMethodNames(name, b.methods); this.methods = Collections.unmodifiableList(new ArrayList<>(b.methods)); this.schemaDescriptor = b.schemaDescriptor; } /** * Simple name of the service. It is not an absolute path. * * @since 1.0.0 */ public String getName() { return name; } /** * A collection of {@link MethodDescriptor} instances describing the methods exposed by the * service. * * @since 1.0.0 */ public Collection> getMethods() { return methods; } /** * Returns the schema descriptor for this service. A schema descriptor is an object that is not * used by gRPC core but includes information related to the service. The type of the object * is specific to the consumer, so both the code setting the schema descriptor and the code * calling {@link #getSchemaDescriptor()} must coordinate. For example, protobuf generated code * sets this value, in order to be consumed by the server reflection service. See also: * {@code io.grpc.protobuf.ProtoFileDescriptorSupplier}. * * @since 1.1.0 */ @Nullable @ExperimentalApi("https://github.com/grpc/grpc-java/issues/2222") public Object getSchemaDescriptor() { return schemaDescriptor; } static void validateMethodNames(String serviceName, Collection> methods) { Set allNames = new HashSet<>(methods.size()); for (MethodDescriptor method : methods) { checkNotNull(method, "method"); String methodServiceName = method.getServiceName(); checkArgument(serviceName.equals(methodServiceName), "service names %s != %s", methodServiceName, serviceName); checkArgument(allNames.add(method.getFullMethodName()), "duplicate name %s", method.getFullMethodName()); } } /** * Creates a new builder for a {@link ServiceDescriptor}. * * @since 1.1.0 */ public static Builder newBuilder(String name) { return new Builder(name); } /** * A builder for a {@link ServiceDescriptor}. * * @since 1.1.0 */ public static final class Builder { private Builder(String name) { setName(name); } private String name; private List> methods = new ArrayList<>(); private Object schemaDescriptor; /** * Sets the name. This should be non-{@code null}. * * @param name The name of the service. * @return this builder. * @since 1.1.0 */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/2666") public Builder setName(String name) { this.name = checkNotNull(name, "name"); return this; } /** * Adds a method to this service. This should be non-{@code null}. * * @param method the method to add to the descriptor. * @return this builder. * @since 1.1.0 */ public Builder addMethod(MethodDescriptor method) { methods.add(checkNotNull(method, "method")); return this; } /** * Currently not exposed. Bulk adds methods to this builder. * * @param methods the methods to add. * @return this builder. */ private Builder addAllMethods(Collection> methods) { this.methods.addAll(methods); return this; } /** * Sets the schema descriptor for this builder. A schema descriptor is an object that is not * used by gRPC core but includes information related to the service. The type of the object * is specific to the consumer, so both the code calling this and the code calling * {@link ServiceDescriptor#getSchemaDescriptor()} must coordinate. For example, protobuf * generated code sets this value, in order to be consumed by the server reflection service. * * @param schemaDescriptor an object that describes the service structure. Should be immutable. * @return this builder. * @since 1.1.0 */ public Builder setSchemaDescriptor(@Nullable Object schemaDescriptor) { this.schemaDescriptor = schemaDescriptor; return this; } /** * Constructs a new {@link ServiceDescriptor}. {@link #setName} should have been called with a * non-{@code null} value before calling this. * * @return a new ServiceDescriptor * @since 1.1.0 */ public ServiceDescriptor build() { return new ServiceDescriptor(this); } } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("name", name) .add("schemaDescriptor", schemaDescriptor) .add("methods", methods) .omitNullValues() .toString(); } }