All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nl.topicus.jdbc.shaded.io.grpc.stub.ServerCalls Maven / Gradle / Ivy

There is a newer version: 1.1.6
Show newest version
/*
 * Copyright 2014, Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *    * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *
 *    * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package nl.topicus.jdbc.shaded.io.grpc.stub;

import static nl.topicus.jdbc.shaded.com.google.nl.topicus.jdbc.shaded.com.on.base.Preconditions.checkNotNull;

import nl.topicus.jdbc.shaded.io.grpc.Metadata;
import nl.topicus.jdbc.shaded.io.grpc.MethodDescriptor;
import nl.topicus.jdbc.shaded.io.grpc.ServerCall;
import nl.topicus.jdbc.shaded.io.grpc.ServerCallHandler;
import nl.topicus.jdbc.shaded.io.grpc.Status;

/**
 * Utility functions for adapting {@link ServerCallHandler}s to application service implementation,
 * meant to be used by the generated code.
 */
public final class ServerCalls {

  private ServerCalls() {
  }

  /**
   * Creates a {@code ServerCallHandler} for a unary call method of the service.
   *
   * @param method an adaptor to the actual method on the service implementation.
   */
  public static  ServerCallHandler asyncUnaryCall(
      final UnaryMethod method) {
    return asyncUnaryRequestCall(method);
  }

  /**
   * Creates a {@code ServerCallHandler} for a server streaming method of the service.
   *
   * @param method an adaptor to the actual method on the service implementation.
   */
  public static  ServerCallHandler asyncServerStreamingCall(
      final ServerStreamingMethod method) {
    return asyncUnaryRequestCall(method);
  }

  /**
   * Creates a {@code ServerCallHandler} for a client streaming method of the service.
   *
   * @param method an adaptor to the actual method on the service implementation.
   */
  public static  ServerCallHandler asyncClientStreamingCall(
      final ClientStreamingMethod method) {
    return asyncStreamingRequestCall(method);
  }

  /**
   * Creates a {@code ServerCallHandler} for a bidi streaming method of the service.
   *
   * @param method an adaptor to the actual method on the service implementation.
   */
  public static  ServerCallHandler asyncBidiStreamingCall(
      final BidiStreamingMethod method) {
    return asyncStreamingRequestCall(method);
  }

  /**
   * Adaptor to a unary call method.
   */
  public static interface UnaryMethod extends UnaryRequestMethod {
  }

  /**
   * Adaptor to a server streaming method.
   */
  public static interface ServerStreamingMethod
      extends UnaryRequestMethod {
  }

  /**
   * Adaptor to a client streaming method.
   */
  public static interface ClientStreamingMethod
      extends StreamingRequestMethod {
  }

  /**
   * Adaptor to a bi-directional streaming method.
   */
  public static interface BidiStreamingMethod
      extends StreamingRequestMethod {
  }

  /**
   * Creates a {@code ServerCallHandler} for a unary request call method of the service.
   *
   * @param method an adaptor to the actual method on the service implementation.
   */
  private static  ServerCallHandler asyncUnaryRequestCall(
      final UnaryRequestMethod method) {
    return new ServerCallHandler() {
      @Override
      public ServerCall.Listener startCall(
          final ServerCall call,
          Metadata headers) {
        final ServerCallStreamObserverImpl responseObserver =
            new ServerCallStreamObserverImpl(call);
        // We expect only 1 request, but we ask for 2 requests here so that if a misbehaving client
        // sends more than 1 requests, ServerCall will catch it. Note that disabling auto
        // inbound flow control has no effect on unary calls.
        call.request(2);
        return new EmptyServerCallListener() {
          ReqT request;
          @Override
          public void onMessage(ReqT request) {
            // We delay calling method.invoke() until onHalfClose() to make sure the client
            // half-closes.
            this.request = request;
          }

          @Override
          public void onHalfClose() {
            if (request != null) {
              method.invoke(request, responseObserver);
              responseObserver.freeze();
              if (call.isReady()) {
                // Since we are calling invoke in halfClose we have missed the onReady
                // event from the transport so recover it here.
                onReady();
              }
            } else {
              call.close(Status.INTERNAL.withDescription("Half-closed without a request"),
                  new Metadata());
            }
          }

          @Override
          public void onCancel() {
            responseObserver.cancelled = true;
            if (responseObserver.onCancelHandler != null) {
              responseObserver.onCancelHandler.run();
            }
          }

          @Override
          public void onReady() {
            if (responseObserver.onReadyHandler != null) {
              responseObserver.onReadyHandler.run();
            }
          }
        };
      }
    };
  }

  /**
   * Creates a {@code ServerCallHandler} for a streaming request call method of the service.
   *
   * @param method an adaptor to the actual method on the service implementation.
   */
  private static  ServerCallHandler asyncStreamingRequestCall(
      final StreamingRequestMethod method) {
    return new ServerCallHandler() {
      @Override
      public ServerCall.Listener startCall(
          final ServerCall call,
          Metadata headers) {
        final ServerCallStreamObserverImpl responseObserver =
            new ServerCallStreamObserverImpl(call);
        final StreamObserver requestObserver = method.invoke(responseObserver);
        responseObserver.freeze();
        if (responseObserver.autoFlowControlEnabled) {
          call.request(1);
        }
        return new EmptyServerCallListener() {
          boolean halfClosed = false;

          @Override
          public void onMessage(ReqT request) {
            requestObserver.onNext(request);

            // Request delivery of the next inbound message.
            if (responseObserver.autoFlowControlEnabled) {
              call.request(1);
            }
          }

          @Override
          public void onHalfClose() {
            halfClosed = true;
            requestObserver.onCompleted();
          }

          @Override
          public void onCancel() {
            responseObserver.cancelled = true;
            if (responseObserver.onCancelHandler != null) {
              responseObserver.onCancelHandler.run();
            }
            if (!halfClosed) {
              requestObserver.onError(Status.CANCELLED.asException());
            }
          }

          @Override
          public void onReady() {
            if (responseObserver.onReadyHandler != null) {
              responseObserver.onReadyHandler.run();
            }
          }
        };
      }
    };
  }

  private static interface UnaryRequestMethod {
    void invoke(ReqT request, StreamObserver responseObserver);
  }

  private static interface StreamingRequestMethod {
    StreamObserver invoke(StreamObserver responseObserver);
  }

  private static final class ServerCallStreamObserverImpl
      extends ServerCallStreamObserver {
    final ServerCall call;
    volatile boolean cancelled;
    private boolean frozen;
    private boolean autoFlowControlEnabled = true;
    private boolean sentHeaders;
    private Runnable onReadyHandler;
    private Runnable onCancelHandler;

    ServerCallStreamObserverImpl(ServerCall call) {
      this.call = call;
    }

    private void freeze() {
      this.frozen = true;
    }

    @Override
    public void setMessageCompression(boolean enable) {
      call.setMessageCompression(enable);
    }

    @Override
    public void setCompression(String nl.topicus.jdbc.shaded.com.ression) {
      call.setCompression(nl.topicus.jdbc.shaded.com.ression);
    }

    @Override
    public void onNext(RespT response) {
      if (cancelled) {
        throw Status.CANCELLED.asRuntimeException();
      }
      if (!sentHeaders) {
        call.sendHeaders(new Metadata());
        sentHeaders = true;
      }
      call.sendMessage(response);
    }

    @Override
    public void onError(Throwable t) {
      Metadata metadata = Status.trailersFromThrowable(t);
      if (metadata == null) {
        metadata = new Metadata();
      }
      call.close(Status.fromThrowable(t), metadata);
    }

    @Override
    public void onCompleted() {
      if (cancelled) {
        throw Status.CANCELLED.asRuntimeException();
      } else {
        call.close(Status.OK, new Metadata());
      }
    }

    @Override
    public boolean isReady() {
      return call.isReady();
    }

    @Override
    public void setOnReadyHandler(Runnable r) {
      if (frozen) {
        throw new IllegalStateException("Cannot alter onReadyHandler after initialization");
      }
      this.onReadyHandler = r;
    }

    @Override
    public boolean isCancelled() {
      return call.isCancelled();
    }

    @Override
    public void setOnCancelHandler(Runnable onCancelHandler) {
      if (frozen) {
        throw new IllegalStateException("Cannot alter onCancelHandler after initialization");
      }
      this.onCancelHandler = onCancelHandler;
    }

    @Override
    public void disableAutoInboundFlowControl() {
      if (frozen) {
        throw new IllegalStateException("Cannot disable auto flow control after initialization");
      } else {
        autoFlowControlEnabled = false;
      }
    }

    @Override
    public void request(int count) {
      call.request(count);
    }
  }

  private static class EmptyServerCallListener extends ServerCall.Listener {
    @Override
    public void onMessage(ReqT request) {
    }

    @Override
    public void onHalfClose() {
    }

    @Override
    public void onCancel() {
    }

    @Override
    public void onComplete() {
    }
  }

  /**
   * Sets unimplemented status for method on given response stream for unary call.
   *
   * @param methodDescriptor of method for which error will be thrown.
   * @param responseObserver on which error will be set.
   */
  public static void asyncUnimplementedUnaryCall(MethodDescriptor methodDescriptor,
      StreamObserver responseObserver) {
    checkNotNull(methodDescriptor, "methodDescriptor");
    checkNotNull(responseObserver, "responseObserver");
    responseObserver.onError(Status.UNIMPLEMENTED
        .withDescription(String.format("Method %s is unimplemented",
            methodDescriptor.getFullMethodName()))
        .asException());
  }

  /**
   * Sets unimplemented status for streaming call.
   *
   * @param methodDescriptor of method for which error will be thrown.
   * @param responseObserver on which error will be set.
   */
  public static  StreamObserver asyncUnimplementedStreamingCall(
      MethodDescriptor methodDescriptor, StreamObserver responseObserver) {
    // NB: For streaming call we want to do the same as for unary call. Fail-fast by setting error
    // on responseObserver and then return no-op observer.
    asyncUnimplementedUnaryCall(methodDescriptor, responseObserver);
    return new NoopStreamObserver();
  }

  /**
   * No-op implementation of StreamObserver. Used in abstract stubs for default implementations of
   * methods which throws UNIMPLEMENTED error and tests.
   */
  static class NoopStreamObserver implements StreamObserver {
    @Override
    public void onNext(V value) {
    }

    @Override
    public void onError(Throwable t) {
    }

    @Override
    public void onCompleted() {
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy