io.grpc.ClientInterceptors Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2014 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 com.google.common.base.Preconditions;
import io.grpc.MethodDescriptor.Marshaller;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Utility methods for working with {@link ClientInterceptor}s.
*/
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 extends ClientInterceptor> interceptors) {
List extends ClientInterceptor> 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}
* 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 intercept(Channel channel, ClientInterceptor... interceptors) {
return intercept(channel, Arrays.asList(interceptors));
}
/**
* 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}
* 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 intercept(Channel channel, List extends ClientInterceptor> interceptors) {
Preconditions.checkNotNull(channel, "channel");
for (ClientInterceptor interceptor : interceptors) {
channel = new InterceptorChannel(channel, interceptor);
}
return channel;
}
/**
* Creates a new ClientInterceptor that transforms requests into {@code WReqT} and responses into
* {@code WRespT} before passing them into the {@code interceptor}.
*/
static ClientInterceptor wrapClientInterceptor(
final ClientInterceptor interceptor,
final Marshaller reqMarshaller,
final Marshaller respMarshaller) {
return new ClientInterceptor() {
@Override
public ClientCall interceptCall(
final MethodDescriptor method, CallOptions callOptions, Channel next) {
final MethodDescriptor wrappedMethod =
method.toBuilder(reqMarshaller, respMarshaller).build();
final ClientCall wrappedCall =
interceptor.interceptCall(wrappedMethod, callOptions, next);
return new PartialForwardingClientCall() {
@Override
public void start(final Listener responseListener, Metadata headers) {
wrappedCall.start(new PartialForwardingClientCallListener() {
@Override
public void onMessage(WRespT wMessage) {
InputStream bytes = respMarshaller.stream(wMessage);
RespT message = method.getResponseMarshaller().parse(bytes);
responseListener.onMessage(message);
}
@Override
protected Listener> delegate() {
return responseListener;
}
}, headers);
}
@Override
public void sendMessage(ReqT message) {
InputStream bytes = method.getRequestMarshaller().stream(message);
WReqT wReq = reqMarshaller.parse(bytes);
wrappedCall.sendMessage(wReq);
}
@Override
protected ClientCall, ?> delegate() {
return wrappedCall;
}
};
}
};
}
private static class InterceptorChannel extends Channel {
private final Channel channel;
private final ClientInterceptor interceptor;
private InterceptorChannel(Channel channel, ClientInterceptor interceptor) {
this.channel = channel;
this.interceptor = Preconditions.checkNotNull(interceptor, "interceptor");
}
@Override
public ClientCall newCall(
MethodDescriptor method, CallOptions callOptions) {
return interceptor.interceptCall(method, callOptions, channel);
}
@Override
public String authority() {
return channel.authority();
}
}
private static final ClientCall