From a574159c81c3bb10d5ac24654eccbf06120b4b08 Mon Sep 17 00:00:00 2001 From: William Thurston Date: Wed, 2 Mar 2016 21:19:08 -0800 Subject: [PATCH] Add interceptForward methods for Client and Server --- .../main/java/io/grpc/ClientInterceptors.java | 31 +++++++++++++ .../main/java/io/grpc/ServerInterceptors.java | 33 ++++++++++++++ .../java/io/grpc/ClientInterceptorsTest.java | 42 +++++++++++++++++ .../java/io/grpc/ServerInterceptorsTest.java | 45 +++++++++++++++++++ 4 files changed, 151 insertions(+) diff --git a/core/src/main/java/io/grpc/ClientInterceptors.java b/core/src/main/java/io/grpc/ClientInterceptors.java index a4fbe90b5f..e36b7367fe 100644 --- a/core/src/main/java/io/grpc/ClientInterceptors.java +++ b/core/src/main/java/io/grpc/ClientInterceptors.java @@ -33,7 +33,9 @@ package io.grpc; import com.google.common.base.Preconditions; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -44,6 +46,35 @@ public class ClientInterceptors { // Prevent instantiation private ClientInterceptors() {} + /** + * Create a new {@link Channel} that will call {@code interceptors} before starting a call on the + * given channel. The first interceptor will have its {@link ClientInterceptor#interceptCall} + * called first. + * + * @param channel the underlying channel to intercept. + * @param interceptors array of interceptors to bind to {@code channel}. + * @return a new channel instance with the interceptors applied. + */ + public static Channel interceptForward(Channel channel, ClientInterceptor... interceptors) { + return interceptForward(channel, Arrays.asList(interceptors)); + } + + /** + * Create a new {@link Channel} that will call {@code interceptors} before starting a call on the + * given channel. The first interceptor will have its {@link ClientInterceptor#interceptCall} + * called first. + * + * @param channel the underlying channel to intercept. + * @param interceptors a list of interceptors to bind to {@code channel}. + * @return a new channel instance with the interceptors applied. + */ + public static Channel interceptForward(Channel channel, + List interceptors) { + List copy = new ArrayList(interceptors); + Collections.reverse(copy); + return intercept(channel, copy); + } + /** * Create a new {@link Channel} that will call {@code interceptors} before starting a call on the * given channel. The last interceptor will have its {@link ClientInterceptor#interceptCall} diff --git a/core/src/main/java/io/grpc/ServerInterceptors.java b/core/src/main/java/io/grpc/ServerInterceptors.java index 18331d0e80..96be30219c 100644 --- a/core/src/main/java/io/grpc/ServerInterceptors.java +++ b/core/src/main/java/io/grpc/ServerInterceptors.java @@ -35,7 +35,9 @@ import com.google.common.base.Preconditions; import java.io.BufferedInputStream; import java.io.InputStream; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -45,6 +47,37 @@ public class ServerInterceptors { // Prevent instantiation private ServerInterceptors() {} + /** + * Create a new {@code ServerServiceDefinition} whose {@link ServerCallHandler}s will call + * {@code interceptors} before calling the pre-existing {@code ServerCallHandler}. The first + * interceptor will have its {@link ServerInterceptor#interceptCall} called first. + * + * @param serviceDef the service definition for which to intercept all its methods. + * @param interceptors array of interceptors to apply to the service. + * @return a wrapped version of {@code serviceDef} with the interceptors applied. + */ + public static ServerServiceDefinition interceptForward(ServerServiceDefinition serviceDef, + ServerInterceptor... interceptors) { + return interceptForward(serviceDef, Arrays.asList(interceptors)); + } + + /** + * Create a new {@code ServerServiceDefinition} whose {@link ServerCallHandler}s will call + * {@code interceptors} before calling the pre-existing {@code ServerCallHandler}. The first + * interceptor will have its {@link ServerInterceptor#interceptCall} called first. + * + * @param serviceDef the service definition for which to intercept all its methods. + * @param interceptors list of interceptors to apply to the service. + * @return a wrapped version of {@code serviceDef} with the interceptors applied. + */ + public static ServerServiceDefinition interceptForward( + ServerServiceDefinition serviceDef, + List interceptors) { + List copy = new ArrayList(interceptors); + Collections.reverse(copy); + return intercept(serviceDef, copy); + } + /** * Create a new {@code ServerServiceDefinition} whose {@link ServerCallHandler}s will call * {@code interceptors} before calling the pre-existing {@code ServerCallHandler}. The last diff --git a/core/src/test/java/io/grpc/ClientInterceptorsTest.java b/core/src/test/java/io/grpc/ClientInterceptorsTest.java index 3ce268b5cf..dafb3baa1b 100644 --- a/core/src/test/java/io/grpc/ClientInterceptorsTest.java +++ b/core/src/test/java/io/grpc/ClientInterceptorsTest.java @@ -200,6 +200,48 @@ public class ClientInterceptorsTest { assertEquals(Arrays.asList("i2", "i1", "channel"), order); } + @Test + public void orderedForward() { + final List order = new ArrayList(); + channel = new Channel() { + @SuppressWarnings("unchecked") + @Override + public ClientCall newCall( + MethodDescriptor method, CallOptions callOptions) { + order.add("channel"); + return (ClientCall) call; + } + + @Override + public String authority() { + return null; + } + }; + ClientInterceptor interceptor1 = new ClientInterceptor() { + @Override + public ClientCall interceptCall( + MethodDescriptor method, + CallOptions callOptions, + Channel next) { + order.add("i1"); + return next.newCall(method, callOptions); + } + }; + ClientInterceptor interceptor2 = new ClientInterceptor() { + @Override + public ClientCall interceptCall( + MethodDescriptor method, + CallOptions callOptions, + Channel next) { + order.add("i2"); + return next.newCall(method, callOptions); + } + }; + Channel intercepted = ClientInterceptors.interceptForward(channel, interceptor1, interceptor2); + assertSame(call, intercepted.newCall(method, CallOptions.DEFAULT)); + assertEquals(Arrays.asList("i1", "i2", "channel"), order); + } + @Test public void callOptions() { final CallOptions initialCallOptions = CallOptions.DEFAULT.withDeadlineNanoTime(100L); diff --git a/core/src/test/java/io/grpc/ServerInterceptorsTest.java b/core/src/test/java/io/grpc/ServerInterceptorsTest.java index dfda79601f..af2f0d12cf 100644 --- a/core/src/test/java/io/grpc/ServerInterceptorsTest.java +++ b/core/src/test/java/io/grpc/ServerInterceptorsTest.java @@ -234,6 +234,51 @@ public class ServerInterceptorsTest { assertEquals(Arrays.asList("i2", "i1", "handler"), order); } + @Test + public void orderedForward() { + final List order = new ArrayList(); + handler = new ServerCallHandler() { + @Override + public ServerCall.Listener startCall( + MethodDescriptor method, + ServerCall call, + Metadata headers) { + order.add("handler"); + return listener; + } + }; + ServerInterceptor interceptor1 = new ServerInterceptor() { + @Override + public ServerCall.Listener interceptCall( + MethodDescriptor method, + ServerCall call, + Metadata headers, + ServerCallHandler next) { + order.add("i1"); + return next.startCall(method, call, headers); + } + }; + ServerInterceptor interceptor2 = new ServerInterceptor() { + @Override + public ServerCall.Listener interceptCall( + MethodDescriptor method, + ServerCall call, + Metadata headers, + ServerCallHandler next) { + order.add("i2"); + return next.startCall(method, call, headers); + } + }; + ServerServiceDefinition serviceDefinition = ServerServiceDefinition.builder("basic") + .addMethod(MethodDescriptor.create(MethodType.UNKNOWN, "basic/flow", + requestMarshaller, responseMarshaller), handler).build(); + ServerServiceDefinition intercepted = ServerInterceptors.interceptForward( + serviceDefinition, interceptor1, interceptor2); + assertSame(listener, + getSoleMethod(intercepted).getServerCallHandler().startCall(method, call, headers)); + assertEquals(Arrays.asList("i1", "i2", "handler"), order); + } + @Test public void argumentsPassed() { final MethodDescriptor method2 = MethodDescriptor.create(