mirror of https://github.com/grpc/grpc-java.git
Move inner classes out of Server.
This is only a move with appropriate code changes to use the new class names. The only functional change was changing the visibility of MethodDefinition's constructor to package-private so ServiceDefinition could construct it. ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=73569974
This commit is contained in:
parent
ba71ee91bf
commit
34aede347a
|
|
@ -1,7 +1,7 @@
|
|||
package com.google.net.stubby;
|
||||
|
||||
import com.google.net.stubby.Server.MethodDefinition;
|
||||
import com.google.net.stubby.Server.ServiceDefinition;
|
||||
import com.google.net.stubby.ServerMethodDefinition;
|
||||
import com.google.net.stubby.ServerServiceDefinition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
|
@ -15,19 +15,19 @@ public abstract class HandlerRegistry {
|
|||
|
||||
/** A method definition and its parent's service definition. */
|
||||
public static final class Method {
|
||||
private final ServiceDefinition serviceDef;
|
||||
private final MethodDefinition methodDef;
|
||||
private final ServerServiceDefinition serviceDef;
|
||||
private final ServerMethodDefinition methodDef;
|
||||
|
||||
public Method(ServiceDefinition serviceDef, MethodDefinition methodDef) {
|
||||
public Method(ServerServiceDefinition serviceDef, ServerMethodDefinition methodDef) {
|
||||
this.serviceDef = serviceDef;
|
||||
this.methodDef = methodDef;
|
||||
}
|
||||
|
||||
public ServiceDefinition getServiceDefinition() {
|
||||
public ServerServiceDefinition getServiceDefinition() {
|
||||
return serviceDef;
|
||||
}
|
||||
|
||||
public MethodDefinition getMethodDefinition() {
|
||||
public ServerMethodDefinition getMethodDefinition() {
|
||||
return methodDef;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.google.net.stubby;
|
||||
|
||||
import com.google.net.stubby.Server.ServiceDefinition;
|
||||
import com.google.net.stubby.ServerServiceDefinition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
|
@ -12,9 +12,9 @@ public abstract class MutableHandlerRegistry extends HandlerRegistry {
|
|||
* Returns {@code null}, or previous service if {@code service} replaced an existing service.
|
||||
*/
|
||||
@Nullable
|
||||
public abstract ServiceDefinition addService(ServiceDefinition service);
|
||||
public abstract ServerServiceDefinition addService(ServerServiceDefinition service);
|
||||
|
||||
/** Returns {@code false} if {@code service} was not registered. */
|
||||
@Nullable
|
||||
public abstract boolean removeService(ServiceDefinition service);
|
||||
public abstract boolean removeService(ServerServiceDefinition service);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.google.net.stubby;
|
||||
|
||||
import com.google.net.stubby.Server.MethodDefinition;
|
||||
import com.google.net.stubby.Server.ServiceDefinition;
|
||||
import com.google.net.stubby.ServerMethodDefinition;
|
||||
import com.google.net.stubby.ServerServiceDefinition;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
|
@ -13,17 +13,17 @@ import javax.annotation.concurrent.ThreadSafe;
|
|||
/** Mutable registry implementation of services and their methods for dispatching incoming calls. */
|
||||
@ThreadSafe
|
||||
public final class MutableHandlerRegistryImpl extends MutableHandlerRegistry {
|
||||
private final ConcurrentMap<String, ServiceDefinition> services
|
||||
= new ConcurrentHashMap<String, ServiceDefinition>();
|
||||
private final ConcurrentMap<String, ServerServiceDefinition> services
|
||||
= new ConcurrentHashMap<String, ServerServiceDefinition>();
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ServiceDefinition addService(ServiceDefinition service) {
|
||||
public ServerServiceDefinition addService(ServerServiceDefinition service) {
|
||||
return services.put(service.getName(), service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeService(ServiceDefinition service) {
|
||||
public boolean removeService(ServerServiceDefinition service) {
|
||||
return services.remove(service.getName(), service);
|
||||
}
|
||||
|
||||
|
|
@ -39,11 +39,11 @@ public final class MutableHandlerRegistryImpl extends MutableHandlerRegistry {
|
|||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
ServiceDefinition service = services.get(methodName.substring(0, index));
|
||||
ServerServiceDefinition service = services.get(methodName.substring(0, index));
|
||||
if (service == null) {
|
||||
return null;
|
||||
}
|
||||
MethodDefinition method = service.getMethod(methodName.substring(index + 1));
|
||||
ServerMethodDefinition method = service.getMethod(methodName.substring(index + 1));
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,7 @@
|
|||
package com.google.net.stubby;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.Service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
|
|
@ -18,268 +9,4 @@ import javax.annotation.concurrent.ThreadSafe;
|
|||
* not expected to be implemented by application code or interceptors.
|
||||
*/
|
||||
@ThreadSafe
|
||||
public interface Server extends Service {
|
||||
/** Definition of a service to be exposed via a Server. */
|
||||
final class ServiceDefinition {
|
||||
public static ServiceDefinition.Builder builder(String serviceName) {
|
||||
return new ServiceDefinition.Builder(serviceName);
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final ImmutableList<MethodDefinition> methods;
|
||||
private final ImmutableMap<String, MethodDefinition> methodLookup;
|
||||
|
||||
private ServiceDefinition(String name, ImmutableList<MethodDefinition> methods,
|
||||
Map<String, MethodDefinition> methodLookup) {
|
||||
this.name = name;
|
||||
this.methods = methods;
|
||||
this.methodLookup = ImmutableMap.copyOf(methodLookup);
|
||||
}
|
||||
|
||||
/** Simple name of the service. It is not an absolute path. */
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ImmutableList<MethodDefinition> getMethods() {
|
||||
return methods;
|
||||
}
|
||||
|
||||
public MethodDefinition getMethod(String name) {
|
||||
return methodLookup.get(name);
|
||||
}
|
||||
|
||||
/** Builder for constructing Service instances. */
|
||||
public static final class Builder {
|
||||
private final String serviceName;
|
||||
private final ImmutableList.Builder<MethodDefinition> methods = ImmutableList.builder();
|
||||
private final Map<String, MethodDefinition> methodLookup
|
||||
= new HashMap<String, MethodDefinition>();
|
||||
|
||||
private Builder(String serviceName) {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a method to be supported by the service.
|
||||
*
|
||||
* @param name simple name of the method, without the service prefix
|
||||
* @param requestMarshaller marshaller for deserializing incoming requests
|
||||
* @param responseMarshaller marshaller for serializing outgoing responses
|
||||
* @param handler handler for incoming calls
|
||||
*/
|
||||
public <ReqT, RespT> Builder addMethod(String name, Marshaller<ReqT> requestMarshaller,
|
||||
Marshaller<RespT> responseMarshaller, CallHandler<ReqT, RespT> handler) {
|
||||
Preconditions.checkNotNull(name, "name must not be null");
|
||||
if (methodLookup.containsKey(name)) {
|
||||
throw new IllegalStateException("Method by same name already registered");
|
||||
}
|
||||
MethodDefinition def = new MethodDefinition<ReqT, RespT>(name,
|
||||
Preconditions.checkNotNull(requestMarshaller, "requestMarshaller must not be null"),
|
||||
Preconditions.checkNotNull(responseMarshaller, "responseMarshaller must not be null"),
|
||||
Preconditions.checkNotNull(handler, "handler must not be null"));
|
||||
methodLookup.put(name, def);
|
||||
methods.add(def);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Construct new ServiceDefinition. */
|
||||
public ServiceDefinition build() {
|
||||
return new ServiceDefinition(serviceName, methods.build(), methodLookup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Definition of a method supported by a service. */
|
||||
final class MethodDefinition<RequestT, ResponseT> {
|
||||
private final String name;
|
||||
private final Marshaller<RequestT> requestMarshaller;
|
||||
private final Marshaller<ResponseT> responseMarshaller;
|
||||
private final CallHandler<RequestT, ResponseT> handler;
|
||||
|
||||
// MethodDefinition has no form of public construction. It is only created within the context of
|
||||
// a ServiceDefinition.Builder.
|
||||
private MethodDefinition(String name, Marshaller<RequestT> requestMarshaller,
|
||||
Marshaller<ResponseT> responseMarshaller, CallHandler<RequestT, ResponseT> handler) {
|
||||
this.name = name;
|
||||
this.requestMarshaller = requestMarshaller;
|
||||
this.responseMarshaller = responseMarshaller;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
/** The simple name of the method. It is not an absolute path. */
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/** Marshaller for deserializing incoming requests. */
|
||||
public Marshaller<RequestT> getRequestMarshaller() {
|
||||
return requestMarshaller;
|
||||
}
|
||||
|
||||
/** Marshaller for serializing outgoing responses. */
|
||||
public Marshaller<ResponseT> getResponseMarshaller() {
|
||||
return responseMarshaller;
|
||||
}
|
||||
|
||||
/** Handler for incoming calls. */
|
||||
public CallHandler<RequestT, ResponseT> getCallHandler() {
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for intercepting incoming RPCs before the handler receives them.
|
||||
*/
|
||||
@ThreadSafe
|
||||
interface Interceptor {
|
||||
/**
|
||||
* Intercept a new call. General semantics of {@link Server.CallHandler#startCall} apply. {@code
|
||||
* next} may only be called once. Returned listener must not be {@code null}.
|
||||
*
|
||||
* <p>If the implementation throws an exception, {@code call} will be closed with an error.
|
||||
* Implementations must not throw an exception if they started processing that may use {@code
|
||||
* call} on another thread.
|
||||
*
|
||||
* @param method metadata concerning the call
|
||||
* @param call object for responding
|
||||
* @param next next processor in the interceptor chain
|
||||
* @return listener for processing incoming messages for {@code call}
|
||||
*/
|
||||
<ReqT, RespT> Server.Call.Listener<ReqT> interceptCall(MethodDescriptor<ReqT, RespT> method,
|
||||
Server.Call<ReqT, RespT> call, CallHandler<ReqT, RespT> next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface to begin processing incoming RPCs. Advanced applications and generated code implement
|
||||
* this interface to implement service methods.
|
||||
*/
|
||||
@ThreadSafe
|
||||
interface CallHandler<ReqT, RespT> {
|
||||
/**
|
||||
* Produce a non-{@code null} listener for the incoming call. Implementations are free to call
|
||||
* methods on {@code call} before this method has returned.
|
||||
*
|
||||
* <p>If the implementation throws an exception, {@code call} will be closed with an error.
|
||||
* Implementations must not throw an exception if they started processing that may use {@code
|
||||
* call} on another thread.
|
||||
*
|
||||
* @param method metadata concerning the call
|
||||
* @param call object for responding
|
||||
* @return listener for processing incoming messages for {@code call}
|
||||
*/
|
||||
Server.Call.Listener<ReqT> startCall(MethodDescriptor<ReqT, RespT> method,
|
||||
Server.Call<ReqT, RespT> call);
|
||||
}
|
||||
|
||||
/**
|
||||
* Low-level method for communicating with a remote client during a single RPC. Unlike normal
|
||||
* RPCs, calls may stream any number of requests and responses, although a single request and
|
||||
* single response is most common. This API is generally intended for use generated handlers, but
|
||||
* advanced applications may have need for it.
|
||||
*
|
||||
* <p>Any contexts must be sent before any payloads, which must be sent before closing.
|
||||
*
|
||||
* <p>No generic method for determining message receipt or providing acknowlegement is provided.
|
||||
* Applications are expected to utilize normal payload messages for such signals, as a response
|
||||
* natually acknowledges its request.
|
||||
*
|
||||
* <p>Methods are guaranteed to be non-blocking. Implementations are not required to be
|
||||
* thread-safe.
|
||||
*/
|
||||
abstract class Call<RequestT, ResponseT> {
|
||||
/**
|
||||
* Callbacks for consuming incoming RPC messages.
|
||||
*
|
||||
* <p>Any contexts are guaranteed to arrive before any payloads, which are guaranteed before
|
||||
* half close, which is guaranteed before completion.
|
||||
*
|
||||
* <p>Implementations are free to block for extended periods of time. Implementations are not
|
||||
* required to be thread-safe.
|
||||
*/
|
||||
// TODO(user): We need to decide what to do in the case of server closing with non-cancellation
|
||||
// before client half closes. It may be that we treat such a case as an error. If we permit such
|
||||
// a case then we either get to generate a half close or purposefully omit it.
|
||||
public abstract static class Listener<T> {
|
||||
/**
|
||||
* A request context has been received. Any context messages will precede payload messages.
|
||||
*
|
||||
* <p>The {@code value} {@link InputStream} will be closed when the returned future completes.
|
||||
* If no future is returned, the value will be closed immediately after returning from this
|
||||
* method.
|
||||
*/
|
||||
@Nullable
|
||||
public abstract ListenableFuture<Void> onContext(String name, InputStream value);
|
||||
|
||||
/**
|
||||
* A request payload has been receiveed. For streaming calls, there may be zero payload
|
||||
* messages.
|
||||
*/
|
||||
@Nullable
|
||||
public abstract ListenableFuture<Void> onPayload(T payload);
|
||||
|
||||
/**
|
||||
* The client completed all message sending. However, the call may still be cancelled.
|
||||
*/
|
||||
public abstract void onHalfClose();
|
||||
|
||||
/**
|
||||
* The call was cancelled and the server is encouraged to abort processing to save resources,
|
||||
* since the client will not process any further messages. Cancellations can be caused by
|
||||
* timeouts, explicit cancel by client, network errors, and similar.
|
||||
*
|
||||
* <p>There will be no further callbacks for the call.
|
||||
*/
|
||||
public abstract void onCancel();
|
||||
|
||||
/**
|
||||
* The call is considered complete and {@link #onCancel} is guaranteed not to be called.
|
||||
* However, the client is not guaranteed to have received all messages.
|
||||
*
|
||||
* <p>There will be no further callbacks for the call.
|
||||
*/
|
||||
public abstract void onCompleted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the call with the provided status. No further sending or receiving will occur. If
|
||||
* {@code status} is not equal to {@link Status#OK}, then the call is said to have failed.
|
||||
*
|
||||
* <p>If {@code status} is not {@link Status#CANCELLED} and no errors or cancellations are known
|
||||
* to have occured, then a {@link Listener#onCompleted} notification should be expected.
|
||||
* Otherwise {@link Listener#onCancel} has been or will be called.
|
||||
*
|
||||
* @throws IllegalStateException if call is already {@code close}d
|
||||
*/
|
||||
public abstract void close(Status status);
|
||||
|
||||
/**
|
||||
* Send a context message. Context messages are intended for side-channel information like
|
||||
* statistics and authentication.
|
||||
*
|
||||
* @param name key identifier of context
|
||||
* @param value context value bytes
|
||||
* @throws IllegalStateException if call is {@link #close}d, or after {@link #sendPayload}
|
||||
*/
|
||||
public abstract void sendContext(String name, InputStream value);
|
||||
|
||||
/**
|
||||
* Send a payload message. Payload messages are the primary form of communication associated
|
||||
* with RPCs. Multiple payload messages may exist for streaming calls.
|
||||
*
|
||||
* @param payload message
|
||||
* @throws IllegalStateException if call is {@link #close}d
|
||||
*/
|
||||
public abstract void sendPayload(ResponseT payload);
|
||||
|
||||
/**
|
||||
* Returns {@code true} when the call is cancelled and the server is encouraged to abort
|
||||
* processing to save resources, since the client will not be processing any further methods.
|
||||
* Cancellations can be caused by timeouts, explicit cancel by client, network errors, and
|
||||
* similar.
|
||||
*
|
||||
* <p>This method may safely be called concurrently from multiple threads.
|
||||
*/
|
||||
public abstract boolean isCancelled();
|
||||
}
|
||||
}
|
||||
public interface Server extends Service {}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,116 @@
|
|||
package com.google.net.stubby;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
import java.io.InputStream;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Low-level method for communicating with a remote client during a single RPC. Unlike normal RPCs,
|
||||
* calls may stream any number of requests and responses, although a single request and single
|
||||
* response is most common. This API is generally intended for use generated handlers, but advanced
|
||||
* applications may have need for it.
|
||||
*
|
||||
* <p>Any contexts must be sent before any payloads, which must be sent before closing.
|
||||
*
|
||||
* <p>No generic method for determining message receipt or providing acknowlegement is provided.
|
||||
* Applications are expected to utilize normal payload messages for such signals, as a response
|
||||
* natually acknowledges its request.
|
||||
*
|
||||
* <p>Methods are guaranteed to be non-blocking. Implementations are not required to be thread-safe.
|
||||
*/
|
||||
public abstract class ServerCall<RequestT, ResponseT> {
|
||||
/**
|
||||
* Callbacks for consuming incoming RPC messages.
|
||||
*
|
||||
* <p>Any contexts are guaranteed to arrive before any payloads, which are guaranteed before half
|
||||
* close, which is guaranteed before completion.
|
||||
*
|
||||
* <p>Implementations are free to block for extended periods of time. Implementations are not
|
||||
* required to be thread-safe.
|
||||
*/
|
||||
// TODO(user): We need to decide what to do in the case of server closing with non-cancellation
|
||||
// before client half closes. It may be that we treat such a case as an error. If we permit such
|
||||
// a case then we either get to generate a half close or purposefully omit it.
|
||||
public abstract static class Listener<T> {
|
||||
/**
|
||||
* A request context has been received. Any context messages will precede payload messages.
|
||||
*
|
||||
* <p>The {@code value} {@link InputStream} will be closed when the returned future completes.
|
||||
* If no future is returned, the value will be closed immediately after returning from this
|
||||
* method.
|
||||
*/
|
||||
@Nullable
|
||||
public abstract ListenableFuture<Void> onContext(String name, InputStream value);
|
||||
|
||||
/**
|
||||
* A request payload has been receiveed. For streaming calls, there may be zero payload
|
||||
* messages.
|
||||
*/
|
||||
@Nullable
|
||||
public abstract ListenableFuture<Void> onPayload(T payload);
|
||||
|
||||
/**
|
||||
* The client completed all message sending. However, the call may still be cancelled.
|
||||
*/
|
||||
public abstract void onHalfClose();
|
||||
|
||||
/**
|
||||
* The call was cancelled and the server is encouraged to abort processing to save resources,
|
||||
* since the client will not process any further messages. Cancellations can be caused by
|
||||
* timeouts, explicit cancel by client, network errors, and similar.
|
||||
*
|
||||
* <p>There will be no further callbacks for the call.
|
||||
*/
|
||||
public abstract void onCancel();
|
||||
|
||||
/**
|
||||
* The call is considered complete and {@link #onCancel} is guaranteed not to be called.
|
||||
* However, the client is not guaranteed to have received all messages.
|
||||
*
|
||||
* <p>There will be no further callbacks for the call.
|
||||
*/
|
||||
public abstract void onCompleted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the call with the provided status. No further sending or receiving will occur. If {@code
|
||||
* status} is not equal to {@link Status#OK}, then the call is said to have failed.
|
||||
*
|
||||
* <p>If {@code status} is not {@link Status#CANCELLED} and no errors or cancellations are known
|
||||
* to have occured, then a {@link Listener#onCompleted} notification should be expected.
|
||||
* Otherwise {@link Listener#onCancel} has been or will be called.
|
||||
*
|
||||
* @throws IllegalStateException if call is already {@code close}d
|
||||
*/
|
||||
public abstract void close(Status status);
|
||||
|
||||
/**
|
||||
* Send a context message. Context messages are intended for side-channel information like
|
||||
* statistics and authentication.
|
||||
*
|
||||
* @param name key identifier of context
|
||||
* @param value context value bytes
|
||||
* @throws IllegalStateException if call is {@link #close}d, or after {@link #sendPayload}
|
||||
*/
|
||||
public abstract void sendContext(String name, InputStream value);
|
||||
|
||||
/**
|
||||
* Send a payload message. Payload messages are the primary form of communication associated with
|
||||
* RPCs. Multiple payload messages may exist for streaming calls.
|
||||
*
|
||||
* @param payload message
|
||||
* @throws IllegalStateException if call is {@link #close}d
|
||||
*/
|
||||
public abstract void sendPayload(ResponseT payload);
|
||||
|
||||
/**
|
||||
* Returns {@code true} when the call is cancelled and the server is encouraged to abort
|
||||
* processing to save resources, since the client will not be processing any further methods.
|
||||
* Cancellations can be caused by timeouts, explicit cancel by client, network errors, and
|
||||
* similar.
|
||||
*
|
||||
* <p>This method may safely be called concurrently from multiple threads.
|
||||
*/
|
||||
public abstract boolean isCancelled();
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.google.net.stubby;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Interface to begin processing incoming RPCs. Advanced applications and generated code implement
|
||||
* this interface to implement service methods.
|
||||
*/
|
||||
@ThreadSafe
|
||||
public interface ServerCallHandler<ReqT, RespT> {
|
||||
/**
|
||||
* Produce a non-{@code null} listener for the incoming call. Implementations are free to call
|
||||
* methods on {@code call} before this method has returned.
|
||||
*
|
||||
* <p>If the implementation throws an exception, {@code call} will be closed with an error.
|
||||
* Implementations must not throw an exception if they started processing that may use {@code
|
||||
* call} on another thread.
|
||||
*
|
||||
* @param method metadata concerning the call
|
||||
* @param call object for responding
|
||||
* @return listener for processing incoming messages for {@code call}
|
||||
*/
|
||||
ServerCall.Listener<ReqT> startCall(MethodDescriptor<ReqT, RespT> method,
|
||||
ServerCall<ReqT, RespT> call);
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.google.net.stubby;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Interface for intercepting incoming RPCs before the handler receives them.
|
||||
*/
|
||||
@ThreadSafe
|
||||
public interface ServerInterceptor {
|
||||
/**
|
||||
* Intercept a new call. General semantics of {@link ServerCallHandler#startCall} apply. {@code
|
||||
* next} may only be called once. Returned listener must not be {@code null}.
|
||||
*
|
||||
* <p>If the implementation throws an exception, {@code call} will be closed with an error.
|
||||
* Implementations must not throw an exception if they started processing that may use {@code
|
||||
* call} on another thread.
|
||||
*
|
||||
* @param method metadata concerning the call
|
||||
* @param call object for responding
|
||||
* @param next next processor in the interceptor chain
|
||||
* @return listener for processing incoming messages for {@code call}
|
||||
*/
|
||||
<ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(MethodDescriptor<ReqT, RespT> method,
|
||||
ServerCall<ReqT, RespT> call, ServerCallHandler<ReqT, RespT> next);
|
||||
}
|
||||
|
|
@ -2,87 +2,89 @@ package com.google.net.stubby;
|
|||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.net.stubby.Server.CallHandler;
|
||||
import com.google.net.stubby.Server.Interceptor;
|
||||
import com.google.net.stubby.Server.MethodDefinition;
|
||||
import com.google.net.stubby.Server.ServiceDefinition;
|
||||
import com.google.net.stubby.ServerMethodDefinition;
|
||||
import com.google.net.stubby.ServerCallHandler;
|
||||
import com.google.net.stubby.ServerInterceptor;
|
||||
import com.google.net.stubby.ServerServiceDefinition;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
|
||||
/** Utility class for {@link Server.Interceptor}s. */
|
||||
/** Utility class for {@link ServerInterceptor}s. */
|
||||
public class ServerInterceptors {
|
||||
// Prevent instantiation
|
||||
private ServerInterceptors() {}
|
||||
|
||||
/**
|
||||
* Create a new {@code ServiceDefinition} whose {@link Server.CallHandler}s will call {@code
|
||||
* interceptors} before calling the pre-existing {@code CallHandler}.
|
||||
* Create a new {@code ServerServiceDefinition} whose {@link ServerCallHandler}s will call {@code
|
||||
* interceptors} before calling the pre-existing {@code ServerCallHandler}.
|
||||
*/
|
||||
public static ServiceDefinition intercept(ServiceDefinition serviceDef,
|
||||
List<Interceptor> interceptors) {
|
||||
public static ServerServiceDefinition intercept(ServerServiceDefinition serviceDef,
|
||||
List<ServerInterceptor> interceptors) {
|
||||
Preconditions.checkNotNull(serviceDef);
|
||||
List<Interceptor> immutableInterceptors = ImmutableList.copyOf(interceptors);
|
||||
List<ServerInterceptor> immutableInterceptors = ImmutableList.copyOf(interceptors);
|
||||
if (immutableInterceptors.isEmpty()) {
|
||||
return serviceDef;
|
||||
}
|
||||
ServiceDefinition.Builder serviceDefBuilder = ServiceDefinition.builder(serviceDef.getName());
|
||||
for (MethodDefinition<?, ?> method : serviceDef.getMethods()) {
|
||||
ServerServiceDefinition.Builder serviceDefBuilder
|
||||
= ServerServiceDefinition.builder(serviceDef.getName());
|
||||
for (ServerMethodDefinition<?, ?> method : serviceDef.getMethods()) {
|
||||
wrapAndAddMethod(serviceDefBuilder, method, immutableInterceptors);
|
||||
}
|
||||
return serviceDefBuilder.build();
|
||||
}
|
||||
|
||||
private static <ReqT, RespT> void wrapAndAddMethod(ServiceDefinition.Builder serviceDefBuilder,
|
||||
MethodDefinition<ReqT, RespT> method, List<Interceptor> interceptors) {
|
||||
CallHandler<ReqT, RespT> callHandler
|
||||
= InterceptCallHandler.create(interceptors, method.getCallHandler());
|
||||
private static <ReqT, RespT> void wrapAndAddMethod(
|
||||
ServerServiceDefinition.Builder serviceDefBuilder, ServerMethodDefinition<ReqT, RespT> method,
|
||||
List<ServerInterceptor> interceptors) {
|
||||
ServerCallHandler<ReqT, RespT> callHandler
|
||||
= InterceptCallHandler.create(interceptors, method.getServerCallHandler());
|
||||
serviceDefBuilder.addMethod(method.getName(), method.getRequestMarshaller(),
|
||||
method.getResponseMarshaller(), callHandler);
|
||||
}
|
||||
|
||||
private static class InterceptCallHandler<ReqT, RespT> implements CallHandler<ReqT, RespT> {
|
||||
private static class InterceptCallHandler<ReqT, RespT> implements ServerCallHandler<ReqT, RespT> {
|
||||
public static <ReqT, RespT> InterceptCallHandler<ReqT, RespT> create(
|
||||
List<Interceptor> interceptors, CallHandler<ReqT, RespT> callHandler) {
|
||||
List<ServerInterceptor> interceptors, ServerCallHandler<ReqT, RespT> callHandler) {
|
||||
return new InterceptCallHandler<ReqT, RespT>(interceptors, callHandler);
|
||||
}
|
||||
|
||||
private final List<Interceptor> interceptors;
|
||||
private final CallHandler<ReqT, RespT> callHandler;
|
||||
private final List<ServerInterceptor> interceptors;
|
||||
private final ServerCallHandler<ReqT, RespT> callHandler;
|
||||
|
||||
private InterceptCallHandler(List<Interceptor> interceptors,
|
||||
CallHandler<ReqT, RespT> callHandler) {
|
||||
private InterceptCallHandler(List<ServerInterceptor> interceptors,
|
||||
ServerCallHandler<ReqT, RespT> callHandler) {
|
||||
this.interceptors = interceptors;
|
||||
this.callHandler = callHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Server.Call.Listener<ReqT> startCall(MethodDescriptor<ReqT, RespT> method,
|
||||
Server.Call<ReqT, RespT> call) {
|
||||
public ServerCall.Listener<ReqT> startCall(MethodDescriptor<ReqT, RespT> method,
|
||||
ServerCall<ReqT, RespT> call) {
|
||||
return ProcessInterceptorsCallHandler.create(interceptors.iterator(), callHandler)
|
||||
.startCall(method, call);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ProcessInterceptorsCallHandler<ReqT, RespT>
|
||||
implements CallHandler<ReqT, RespT> {
|
||||
implements ServerCallHandler<ReqT, RespT> {
|
||||
public static <ReqT, RespT> ProcessInterceptorsCallHandler<ReqT, RespT> create(
|
||||
Iterator<Interceptor> interceptors, CallHandler<ReqT, RespT> callHandler) {
|
||||
Iterator<ServerInterceptor> interceptors, ServerCallHandler<ReqT, RespT> callHandler) {
|
||||
return new ProcessInterceptorsCallHandler<ReqT, RespT>(interceptors, callHandler);
|
||||
}
|
||||
|
||||
private Iterator<Interceptor> interceptors;
|
||||
private final CallHandler<ReqT, RespT> callHandler;
|
||||
private Iterator<ServerInterceptor> interceptors;
|
||||
private final ServerCallHandler<ReqT, RespT> callHandler;
|
||||
|
||||
private ProcessInterceptorsCallHandler(Iterator<Interceptor> interceptors,
|
||||
CallHandler<ReqT, RespT> callHandler) {
|
||||
private ProcessInterceptorsCallHandler(Iterator<ServerInterceptor> interceptors,
|
||||
ServerCallHandler<ReqT, RespT> callHandler) {
|
||||
this.interceptors = interceptors;
|
||||
this.callHandler = callHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Server.Call.Listener<ReqT> startCall(MethodDescriptor<ReqT, RespT> method,
|
||||
Server.Call<ReqT, RespT> call) {
|
||||
public ServerCall.Listener<ReqT> startCall(MethodDescriptor<ReqT, RespT> method,
|
||||
ServerCall<ReqT, RespT> call) {
|
||||
if (interceptors != null && interceptors.hasNext()) {
|
||||
return interceptors.next().interceptCall(method, call, this);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
package com.google.net.stubby;
|
||||
|
||||
/** Definition of a method supported by a service. */
|
||||
public final class ServerMethodDefinition<RequestT, ResponseT> {
|
||||
private final String name;
|
||||
private final Marshaller<RequestT> requestMarshaller;
|
||||
private final Marshaller<ResponseT> responseMarshaller;
|
||||
private final ServerCallHandler<RequestT, ResponseT> handler;
|
||||
|
||||
// ServerMethodDefinition has no form of public construction. It is only created within the
|
||||
// context of a ServerServiceDefinition.Builder.
|
||||
ServerMethodDefinition(String name, Marshaller<RequestT> requestMarshaller,
|
||||
Marshaller<ResponseT> responseMarshaller, ServerCallHandler<RequestT, ResponseT> handler) {
|
||||
this.name = name;
|
||||
this.requestMarshaller = requestMarshaller;
|
||||
this.responseMarshaller = responseMarshaller;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
/** The simple name of the method. It is not an absolute path. */
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/** Marshaller for deserializing incoming requests. */
|
||||
public Marshaller<RequestT> getRequestMarshaller() {
|
||||
return requestMarshaller;
|
||||
}
|
||||
|
||||
/** Marshaller for serializing outgoing responses. */
|
||||
public Marshaller<ResponseT> getResponseMarshaller() {
|
||||
return responseMarshaller;
|
||||
}
|
||||
|
||||
/** Handler for incoming calls. */
|
||||
public ServerCallHandler<RequestT, ResponseT> getServerCallHandler() {
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package com.google.net.stubby;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/** Definition of a service to be exposed via a Server. */
|
||||
public final class ServerServiceDefinition {
|
||||
public static Builder builder(String serviceName) {
|
||||
return new Builder(serviceName);
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final ImmutableList<ServerMethodDefinition> methods;
|
||||
private final ImmutableMap<String, ServerMethodDefinition> methodLookup;
|
||||
|
||||
private ServerServiceDefinition(String name, ImmutableList<ServerMethodDefinition> methods,
|
||||
Map<String, ServerMethodDefinition> methodLookup) {
|
||||
this.name = name;
|
||||
this.methods = methods;
|
||||
this.methodLookup = ImmutableMap.copyOf(methodLookup);
|
||||
}
|
||||
|
||||
/** Simple name of the service. It is not an absolute path. */
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ImmutableList<ServerMethodDefinition> getMethods() {
|
||||
return methods;
|
||||
}
|
||||
|
||||
public ServerMethodDefinition getMethod(String name) {
|
||||
return methodLookup.get(name);
|
||||
}
|
||||
|
||||
/** Builder for constructing Service instances. */
|
||||
public static final class Builder {
|
||||
private final String serviceName;
|
||||
private final ImmutableList.Builder<ServerMethodDefinition> methods = ImmutableList.builder();
|
||||
private final Map<String, ServerMethodDefinition> methodLookup
|
||||
= new HashMap<String, ServerMethodDefinition>();
|
||||
|
||||
private Builder(String serviceName) {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a method to be supported by the service.
|
||||
*
|
||||
* @param name simple name of the method, without the service prefix
|
||||
* @param requestMarshaller marshaller for deserializing incoming requests
|
||||
* @param responseMarshaller marshaller for serializing outgoing responses
|
||||
* @param handler handler for incoming calls
|
||||
*/
|
||||
public <ReqT, RespT> Builder addMethod(String name, Marshaller<ReqT> requestMarshaller,
|
||||
Marshaller<RespT> responseMarshaller, ServerCallHandler<ReqT, RespT> handler) {
|
||||
Preconditions.checkNotNull(name, "name must not be null");
|
||||
if (methodLookup.containsKey(name)) {
|
||||
throw new IllegalStateException("Method by same name already registered");
|
||||
}
|
||||
ServerMethodDefinition def = new ServerMethodDefinition<ReqT, RespT>(name,
|
||||
Preconditions.checkNotNull(requestMarshaller, "requestMarshaller must not be null"),
|
||||
Preconditions.checkNotNull(responseMarshaller, "responseMarshaller must not be null"),
|
||||
Preconditions.checkNotNull(handler, "handler must not be null"));
|
||||
methodLookup.put(name, def);
|
||||
methods.add(def);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Construct new ServerServiceDefinition. */
|
||||
public ServerServiceDefinition build() {
|
||||
return new ServerServiceDefinition(serviceName, methods.build(), methodLookup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,9 +7,9 @@ import static org.junit.Assert.assertSame;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import com.google.net.stubby.Server.CallHandler;
|
||||
import com.google.net.stubby.Server.MethodDefinition;
|
||||
import com.google.net.stubby.Server.ServiceDefinition;
|
||||
import com.google.net.stubby.ServerMethodDefinition;
|
||||
import com.google.net.stubby.ServerCallHandler;
|
||||
import com.google.net.stubby.ServerServiceDefinition;
|
||||
import com.google.net.stubby.HandlerRegistry.Method;
|
||||
|
||||
import org.junit.After;
|
||||
|
|
@ -24,15 +24,16 @@ public class MutableHandlerRegistryImplTest {
|
|||
private MutableHandlerRegistry registry = new MutableHandlerRegistryImpl();
|
||||
private Marshaller<String> requestMarshaller = mock(Marshaller.class);
|
||||
private Marshaller<Integer> responseMarshaller = mock(Marshaller.class);
|
||||
private CallHandler<String, Integer> handler = mock(CallHandler.class);
|
||||
private ServiceDefinition basicServiceDefinition = ServiceDefinition.builder("basic")
|
||||
private ServerCallHandler<String, Integer> handler = mock(ServerCallHandler.class);
|
||||
private ServerServiceDefinition basicServiceDefinition = ServerServiceDefinition.builder("basic")
|
||||
.addMethod("flow", requestMarshaller, responseMarshaller, handler).build();
|
||||
private MethodDefinition flowMethodDefinition = basicServiceDefinition.getMethods().get(0);
|
||||
private ServiceDefinition multiServiceDefinition = ServiceDefinition.builder("multi")
|
||||
private ServerMethodDefinition flowMethodDefinition = basicServiceDefinition.getMethods().get(0);
|
||||
private ServerServiceDefinition multiServiceDefinition = ServerServiceDefinition.builder("multi")
|
||||
.addMethod("couple", requestMarshaller, responseMarshaller, handler)
|
||||
.addMethod("few", requestMarshaller, responseMarshaller, handler).build();
|
||||
private MethodDefinition coupleMethodDefinition = multiServiceDefinition.getMethod("couple");
|
||||
private MethodDefinition fewMethodDefinition = multiServiceDefinition.getMethod("few");
|
||||
private ServerMethodDefinition coupleMethodDefinition
|
||||
= multiServiceDefinition.getMethod("couple");
|
||||
private ServerMethodDefinition fewMethodDefinition = multiServiceDefinition.getMethod("few");
|
||||
|
||||
@After
|
||||
public void makeSureMocksUnused() {
|
||||
|
|
@ -90,9 +91,9 @@ public class MutableHandlerRegistryImplTest {
|
|||
public void replaceAndLookup() {
|
||||
assertNull(registry.addService(basicServiceDefinition));
|
||||
assertNotNull(registry.lookupMethod("/basic.flow"));
|
||||
ServiceDefinition replaceServiceDefinition = ServiceDefinition.builder("basic")
|
||||
ServerServiceDefinition replaceServiceDefinition = ServerServiceDefinition.builder("basic")
|
||||
.addMethod("another", requestMarshaller, responseMarshaller, handler).build();
|
||||
MethodDefinition anotherMethodDefinition = replaceServiceDefinition.getMethods().get(0);
|
||||
ServerMethodDefinition anotherMethodDefinition = replaceServiceDefinition.getMethods().get(0);
|
||||
assertSame(basicServiceDefinition, registry.addService(replaceServiceDefinition));
|
||||
|
||||
assertNull(registry.lookupMethod("/basic.flow"));
|
||||
|
|
@ -122,7 +123,7 @@ public class MutableHandlerRegistryImplTest {
|
|||
@Test
|
||||
public void removeMissingNameConflictFails() {
|
||||
assertNull(registry.addService(basicServiceDefinition));
|
||||
assertFalse(registry.removeService(ServiceDefinition.builder("basic").build()));
|
||||
assertFalse(registry.removeService(ServerServiceDefinition.builder("basic").build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -142,6 +143,6 @@ public class MutableHandlerRegistryImplTest {
|
|||
public void addReturnsPrevious() {
|
||||
assertNull(registry.addService(basicServiceDefinition));
|
||||
assertSame(basicServiceDefinition,
|
||||
registry.addService(ServiceDefinition.builder("basic").build()));
|
||||
registry.addService(ServerServiceDefinition.builder("basic").build()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,10 @@ import static org.mockito.Mockito.verify;
|
|||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
import com.google.net.stubby.Server.Interceptor;
|
||||
import com.google.net.stubby.Server.Call;
|
||||
import com.google.net.stubby.Server.CallHandler;
|
||||
import com.google.net.stubby.Server.MethodDefinition;
|
||||
import com.google.net.stubby.Server.ServiceDefinition;
|
||||
import com.google.net.stubby.ServerInterceptor;
|
||||
import com.google.net.stubby.ServerCall;
|
||||
import com.google.net.stubby.ServerCallHandler;
|
||||
import com.google.net.stubby.ServerServiceDefinition;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
|
@ -31,17 +30,18 @@ import java.util.List;
|
|||
public class ServerInterceptorsTest {
|
||||
private Marshaller<String> requestMarshaller = mock(Marshaller.class);
|
||||
private Marshaller<Integer> responseMarshaller = mock(Marshaller.class);
|
||||
private CallHandler<String, Integer> handler = mock(CallHandler.class);
|
||||
private Call.Listener<String> listener = mock(Call.Listener.class);
|
||||
private ServerCallHandler<String, Integer> handler = mock(ServerCallHandler.class);
|
||||
private ServerCall.Listener<String> listener = mock(ServerCall.Listener.class);
|
||||
private MethodDescriptor<String, Integer> methodDescriptor = mock(MethodDescriptor.class);
|
||||
private Call<String, Integer> call = mock(Call.class);
|
||||
private ServiceDefinition serviceDefinition = ServiceDefinition.builder("basic")
|
||||
private ServerCall<String, Integer> call = mock(ServerCall.class);
|
||||
private ServerServiceDefinition serviceDefinition = ServerServiceDefinition.builder("basic")
|
||||
.addMethod("flow", requestMarshaller, responseMarshaller, handler).build();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
Mockito.when(handler.startCall(
|
||||
Mockito.<MethodDescriptor<String, Integer>>any(), Mockito.<Call<String, Integer>>any()))
|
||||
Mockito.<MethodDescriptor<String, Integer>>any(),
|
||||
Mockito.<ServerCall<String, Integer>>any()))
|
||||
.thenReturn(listener);
|
||||
}
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ public class ServerInterceptorsTest {
|
|||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void npeForNullServiceDefinition() {
|
||||
ServerInterceptors.intercept(null, Arrays.<Interceptor>asList());
|
||||
ServerInterceptors.intercept(null, Arrays.<ServerInterceptor>asList());
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
|
|
@ -65,28 +65,28 @@ public class ServerInterceptorsTest {
|
|||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void npeForNullInterceptor() {
|
||||
ServerInterceptors.intercept(serviceDefinition, Arrays.asList((Interceptor) null));
|
||||
ServerInterceptors.intercept(serviceDefinition, Arrays.asList((ServerInterceptor) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noop() {
|
||||
assertSame(serviceDefinition,
|
||||
ServerInterceptors.intercept(serviceDefinition, Arrays.<Interceptor>asList()));
|
||||
ServerInterceptors.intercept(serviceDefinition, Arrays.<ServerInterceptor>asList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleInvocationsOfHandler() {
|
||||
Interceptor interceptor = Mockito.spy(new NoopInterceptor());
|
||||
ServiceDefinition intercepted
|
||||
ServerInterceptor interceptor = Mockito.spy(new NoopInterceptor());
|
||||
ServerServiceDefinition intercepted
|
||||
= ServerInterceptors.intercept(serviceDefinition, Arrays.asList(interceptor));
|
||||
assertSame(listener,
|
||||
intercepted.getMethods().get(0).getCallHandler().startCall(methodDescriptor, call));
|
||||
intercepted.getMethods().get(0).getServerCallHandler().startCall(methodDescriptor, call));
|
||||
verify(interceptor).interceptCall(same(methodDescriptor), same(call), anyCallHandler());
|
||||
verify(handler).startCall(methodDescriptor, call);
|
||||
verifyNoMoreInteractions(interceptor, handler);
|
||||
|
||||
assertSame(listener,
|
||||
intercepted.getMethods().get(0).getCallHandler().startCall(methodDescriptor, call));
|
||||
intercepted.getMethods().get(0).getServerCallHandler().startCall(methodDescriptor, call));
|
||||
verify(interceptor, times(2))
|
||||
.interceptCall(same(methodDescriptor), same(call), anyCallHandler());
|
||||
verify(handler, times(2)).startCall(methodDescriptor, call);
|
||||
|
|
@ -95,18 +95,18 @@ public class ServerInterceptorsTest {
|
|||
|
||||
@Test
|
||||
public void correctHandlerCalled() {
|
||||
CallHandler<String, Integer> handler2 = Mockito.mock(CallHandler.class);
|
||||
serviceDefinition = ServiceDefinition.builder("basic")
|
||||
ServerCallHandler<String, Integer> handler2 = Mockito.mock(ServerCallHandler.class);
|
||||
serviceDefinition = ServerServiceDefinition.builder("basic")
|
||||
.addMethod("flow", requestMarshaller, responseMarshaller, handler)
|
||||
.addMethod("flow2", requestMarshaller, responseMarshaller, handler2).build();
|
||||
ServiceDefinition intercepted = ServerInterceptors.intercept(
|
||||
serviceDefinition, Arrays.<Interceptor>asList(new NoopInterceptor()));
|
||||
intercepted.getMethod("flow").getCallHandler().startCall(methodDescriptor, call);
|
||||
ServerServiceDefinition intercepted = ServerInterceptors.intercept(
|
||||
serviceDefinition, Arrays.<ServerInterceptor>asList(new NoopInterceptor()));
|
||||
intercepted.getMethod("flow").getServerCallHandler().startCall(methodDescriptor, call);
|
||||
verify(handler).startCall(methodDescriptor, call);
|
||||
verifyNoMoreInteractions(handler);
|
||||
verifyZeroInteractions(handler2);
|
||||
|
||||
intercepted.getMethod("flow2").getCallHandler().startCall(methodDescriptor, call);
|
||||
intercepted.getMethod("flow2").getServerCallHandler().startCall(methodDescriptor, call);
|
||||
verify(handler2).startCall(methodDescriptor, call);
|
||||
verifyNoMoreInteractions(handler);
|
||||
verifyNoMoreInteractions(handler2);
|
||||
|
|
@ -115,72 +115,73 @@ public class ServerInterceptorsTest {
|
|||
@Test
|
||||
public void ordered() {
|
||||
final List<String> order = new ArrayList<String>();
|
||||
handler = new CallHandler<String, Integer>() {
|
||||
handler = new ServerCallHandler<String, Integer>() {
|
||||
@Override
|
||||
public Call.Listener<String> startCall(MethodDescriptor<String, Integer> method,
|
||||
Call<String, Integer> call) {
|
||||
public ServerCall.Listener<String> startCall(MethodDescriptor<String, Integer> method,
|
||||
ServerCall<String, Integer> call) {
|
||||
order.add("handler");
|
||||
return listener;
|
||||
}
|
||||
};
|
||||
Interceptor interceptor1 = new Interceptor() {
|
||||
ServerInterceptor interceptor1 = new ServerInterceptor() {
|
||||
@Override
|
||||
public <ReqT, RespT> Call.Listener<ReqT> interceptCall(
|
||||
MethodDescriptor<ReqT, RespT> method, Call<ReqT, RespT> call,
|
||||
CallHandler<ReqT, RespT> next) {
|
||||
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
|
||||
MethodDescriptor<ReqT, RespT> method, ServerCall<ReqT, RespT> call,
|
||||
ServerCallHandler<ReqT, RespT> next) {
|
||||
order.add("i1");
|
||||
return next.startCall(method, call);
|
||||
}
|
||||
};
|
||||
Interceptor interceptor2 = new Interceptor() {
|
||||
ServerInterceptor interceptor2 = new ServerInterceptor() {
|
||||
@Override
|
||||
public <ReqT, RespT> Call.Listener<ReqT> interceptCall(
|
||||
MethodDescriptor<ReqT, RespT> method, Call<ReqT, RespT> call,
|
||||
CallHandler<ReqT, RespT> next) {
|
||||
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
|
||||
MethodDescriptor<ReqT, RespT> method, ServerCall<ReqT, RespT> call,
|
||||
ServerCallHandler<ReqT, RespT> next) {
|
||||
order.add("i2");
|
||||
return next.startCall(method, call);
|
||||
}
|
||||
};
|
||||
ServiceDefinition serviceDefinition = ServiceDefinition.builder("basic")
|
||||
ServerServiceDefinition serviceDefinition = ServerServiceDefinition.builder("basic")
|
||||
.addMethod("flow", requestMarshaller, responseMarshaller, handler).build();
|
||||
ServiceDefinition intercepted = ServerInterceptors.intercept(
|
||||
ServerServiceDefinition intercepted = ServerInterceptors.intercept(
|
||||
serviceDefinition, Arrays.asList(interceptor1, interceptor2));
|
||||
assertSame(listener,
|
||||
intercepted.getMethods().get(0).getCallHandler().startCall(methodDescriptor, call));
|
||||
intercepted.getMethods().get(0).getServerCallHandler().startCall(methodDescriptor, call));
|
||||
assertEquals(Arrays.asList("i1", "i2", "handler"), order);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void argumentsPassed() {
|
||||
final MethodDescriptor<String, Integer> method2 = mock(MethodDescriptor.class);
|
||||
final Call<String, Integer> call2 = mock(Call.class);
|
||||
final Call.Listener<String> listener2 = mock(Call.Listener.class);
|
||||
Interceptor interceptor = new Interceptor() {
|
||||
final ServerCall<String, Integer> call2 = mock(ServerCall.class);
|
||||
final ServerCall.Listener<String> listener2 = mock(ServerCall.Listener.class);
|
||||
ServerInterceptor interceptor = new ServerInterceptor() {
|
||||
@Override
|
||||
public <ReqT, RespT> Call.Listener<ReqT> interceptCall(
|
||||
MethodDescriptor<ReqT, RespT> method, Call<ReqT, RespT> call,
|
||||
CallHandler<ReqT, RespT> next) {
|
||||
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
|
||||
MethodDescriptor<ReqT, RespT> method, ServerCall<ReqT, RespT> call,
|
||||
ServerCallHandler<ReqT, RespT> next) {
|
||||
assertSame(method, methodDescriptor);
|
||||
assertSame(call, ServerInterceptorsTest.this.call);
|
||||
assertSame(listener, next.startCall((MethodDescriptor) method2, (Call) call2));
|
||||
return (Call.Listener) listener2;
|
||||
assertSame(listener, next.startCall((MethodDescriptor) method2, (ServerCall) call2));
|
||||
return (ServerCall.Listener) listener2;
|
||||
}
|
||||
};
|
||||
ServiceDefinition intercepted = ServerInterceptors.intercept(
|
||||
ServerServiceDefinition intercepted = ServerInterceptors.intercept(
|
||||
serviceDefinition, Arrays.asList(interceptor));
|
||||
assertSame(listener2,
|
||||
intercepted.getMethods().get(0).getCallHandler().startCall(methodDescriptor, call));
|
||||
intercepted.getMethods().get(0).getServerCallHandler().startCall(methodDescriptor, call));
|
||||
verify(handler).startCall(method2, call2);
|
||||
}
|
||||
|
||||
private CallHandler<String, Integer> anyCallHandler() {
|
||||
return Mockito.<CallHandler<String, Integer>>any();
|
||||
private ServerCallHandler<String, Integer> anyCallHandler() {
|
||||
return Mockito.<ServerCallHandler<String, Integer>>any();
|
||||
}
|
||||
|
||||
private static class NoopInterceptor implements Interceptor {
|
||||
private static class NoopInterceptor implements ServerInterceptor {
|
||||
@Override
|
||||
public <ReqT, RespT> Call.Listener<ReqT> interceptCall(MethodDescriptor<ReqT, RespT> method,
|
||||
Call<ReqT, RespT> call, CallHandler<ReqT, RespT> next) {
|
||||
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
|
||||
MethodDescriptor<ReqT, RespT> method, ServerCall<ReqT, RespT> call,
|
||||
ServerCallHandler<ReqT, RespT> next) {
|
||||
return next.startCall(method, call);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue