/*
* Copyright 2016 LINE Corporation
*
* LINE Corporation licenses this file to you 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 com.linecorp.armeria.server.grpc.interop;
import java.io.File;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;
import javax.net.ssl.SSLException;
import com.google.instrumentation.stats.StatsContextFactory;
import com.linecorp.armeria.common.http.HttpSessionProtocols;
import com.linecorp.armeria.server.ServerBuilder;
import com.linecorp.armeria.server.ServiceRequestContext;
import com.linecorp.armeria.server.grpc.GrpcServiceBuilder;
import io.grpc.ServerServiceDefinition;
import io.grpc.ServerStreamTracer.Factory;
import io.grpc.internal.AbstractServerImplBuilder;
import io.grpc.internal.InternalServer;
public class ArmeriaGrpcServerBuilder extends AbstractServerImplBuilder<ArmeriaGrpcServerBuilder> {
private final com.linecorp.armeria.server.ServerBuilder armeriaServerBuilder;
private final GrpcServiceBuilder grpcServiceBuilder;
private final AtomicReference<ServiceRequestContext> ctxCapture;
public ArmeriaGrpcServerBuilder(ServerBuilder armeriaServerBuilder,
GrpcServiceBuilder grpcServiceBuilder,
AtomicReference<ServiceRequestContext> ctxCapture) {
this.armeriaServerBuilder = armeriaServerBuilder;
this.grpcServiceBuilder = grpcServiceBuilder;
this.ctxCapture = ctxCapture;
}
@Override
public ArmeriaGrpcServerBuilder useTransportSecurity(File certChain, File privateKey) {
try {
armeriaServerBuilder.sslContext(HttpSessionProtocols.HTTPS, certChain, privateKey);
} catch (SSLException e) {
throw new IllegalArgumentException(e);
}
return this;
}
@Override
protected ArmeriaGrpcServerBuilder statsContextFactory(StatsContextFactory statsFactory) {
return super.statsContextFactory(NoopStatsContextFactory.INSTANCE);
}
@Override
protected InternalServer buildTransportServer(List<Factory> streamTracerFactories) {
Object registryBuilder = getFieldByReflection("registryBuilder", this, AbstractServerImplBuilder.class);
Map<String, ServerServiceDefinition> services = getFieldByReflection("services", registryBuilder, null);
services.values().forEach(grpcServiceBuilder::addService);
armeriaServerBuilder.serviceUnder("/", grpcServiceBuilder.build()
.decorate((delegate, ctx, req) -> {
ctxCapture.set(ctx);
return delegate.serve(ctx, req);
}));
return new ArmeriaGrpcServer(armeriaServerBuilder.build());
}
@SuppressWarnings("unchecked")
private static <T> T getFieldByReflection(String name, Object instance, @Nullable Class<?> clazz) {
try {
Field field = (clazz != null ? clazz : instance.getClass()).getDeclaredField(name);
field.setAccessible(true);
return (T) field.get(instance);
} catch (Exception e) {
throw new Error(e);
}
}
}