blob: 5cc49100eadc900ab82eb2691b94338807d5ff43 [file] [log] [blame]
/*
* 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 io.grpc.internal;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.instrumentation.stats.Stats;
import com.google.instrumentation.stats.StatsContextFactory;
import io.grpc.BindableService;
import io.grpc.CompressorRegistry;
import io.grpc.Context;
import io.grpc.DecompressorRegistry;
import io.grpc.HandlerRegistry;
import io.grpc.Internal;
import io.grpc.InternalNotifyOnServerBuild;
import io.grpc.ServerBuilder;
import io.grpc.ServerMethodDefinition;
import io.grpc.ServerServiceDefinition;
import io.grpc.ServerTransportFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
import javax.annotation.Nullable;
/**
* The base class for server builders.
*
* @param <T> The concrete type for this builder.
*/
public abstract class AbstractServerImplBuilder<T extends AbstractServerImplBuilder<T>>
extends ServerBuilder<T> {
private static final HandlerRegistry EMPTY_FALLBACK_REGISTRY = new HandlerRegistry() {
@Override
public List<ServerServiceDefinition> getServices() {
return Collections.emptyList();
}
@Override
public ServerMethodDefinition<?, ?> lookupMethod(String methodName,
@Nullable String authority) {
return null;
}
};
private final InternalHandlerRegistry.Builder registryBuilder =
new InternalHandlerRegistry.Builder();
private final ArrayList<ServerTransportFilter> transportFilters =
new ArrayList<ServerTransportFilter>();
private final List<InternalNotifyOnServerBuild> notifyOnBuildList =
new ArrayList<InternalNotifyOnServerBuild>();
@Nullable
private HandlerRegistry fallbackRegistry;
@Nullable
private Executor executor;
@Nullable
private DecompressorRegistry decompressorRegistry;
@Nullable
private CompressorRegistry compressorRegistry;
@Nullable
private StatsContextFactory statsFactory;
@Override
public final T directExecutor() {
return executor(MoreExecutors.directExecutor());
}
@Override
public final T executor(@Nullable Executor executor) {
this.executor = executor;
return thisT();
}
@Override
public final T addService(ServerServiceDefinition service) {
registryBuilder.addService(service);
return thisT();
}
@Override
public final T addService(BindableService bindableService) {
if (bindableService instanceof InternalNotifyOnServerBuild) {
notifyOnBuildList.add((InternalNotifyOnServerBuild) bindableService);
}
return addService(bindableService.bindService());
}
@Override
public final T addTransportFilter(ServerTransportFilter filter) {
transportFilters.add(checkNotNull(filter, "filter"));
return thisT();
}
@Override
public final T fallbackHandlerRegistry(HandlerRegistry registry) {
this.fallbackRegistry = registry;
return thisT();
}
@Override
public final T decompressorRegistry(DecompressorRegistry registry) {
decompressorRegistry = registry;
return thisT();
}
@Override
public final T compressorRegistry(CompressorRegistry registry) {
compressorRegistry = registry;
return thisT();
}
/**
* Override the default stats implementation.
*/
@VisibleForTesting
protected T statsContextFactory(StatsContextFactory statsFactory) {
this.statsFactory = statsFactory;
return thisT();
}
@Override
public ServerImpl build() {
io.grpc.internal.InternalServer transportServer = buildTransportServer();
ServerImpl server = new ServerImpl(getExecutorPool(),
SharedResourcePool.forResource(GrpcUtil.TIMER_SERVICE), registryBuilder.build(),
firstNonNull(fallbackRegistry, EMPTY_FALLBACK_REGISTRY), transportServer,
Context.ROOT, firstNonNull(decompressorRegistry, DecompressorRegistry.getDefaultInstance()),
firstNonNull(compressorRegistry, CompressorRegistry.getDefaultInstance()),
transportFilters,
firstNonNull(statsFactory,
firstNonNull(Stats.getStatsContextFactory(), NoopStatsContextFactory.INSTANCE)),
GrpcUtil.STOPWATCH_SUPPLIER);
for (InternalNotifyOnServerBuild notifyTarget : notifyOnBuildList) {
notifyTarget.notifyOnBuild(server);
}
return server;
}
private ObjectPool<? extends Executor> getExecutorPool() {
final Executor savedExecutor = executor;
if (savedExecutor == null) {
return SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR);
}
return new ObjectPool<Executor>() {
@Override
public Executor getObject() {
return savedExecutor;
}
@Override
public Executor returnObject(Object object) {
return null;
}
};
}
/**
* Children of AbstractServerBuilder should override this method to provide transport specific
* information for the server. This method is mean for Transport implementors and should not be
* used by normal users.
*/
@Internal
protected abstract io.grpc.internal.InternalServer buildTransportServer();
private T thisT() {
@SuppressWarnings("unchecked")
T thisT = (T) this;
return thisT;
}
}