All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glowroot.agent.shaded.grpc.internal.AbstractManagedChannelImplBuilder Maven / Gradle / Ivy

There is a newer version: 0.9.24
Show newest version
/*
 * 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 org.glowroot.agent.shaded.grpc.internal;

import static org.glowroot.agent.shaded.google.common.base.MoreObjects.firstNonNull;

import org.glowroot.agent.shaded.google.common.base.Preconditions;
import org.glowroot.agent.shaded.google.common.util.concurrent.MoreExecutors;

import org.glowroot.agent.shaded.grpc.Attributes;
import org.glowroot.agent.shaded.grpc.ClientInterceptor;
import org.glowroot.agent.shaded.grpc.CompressorRegistry;
import org.glowroot.agent.shaded.grpc.DecompressorRegistry;
import org.glowroot.agent.shaded.grpc.ExperimentalApi;
import org.glowroot.agent.shaded.grpc.LoadBalancer;
import org.glowroot.agent.shaded.grpc.ManagedChannelBuilder;
import org.glowroot.agent.shaded.grpc.NameResolver;
import org.glowroot.agent.shaded.grpc.NameResolverRegistry;
import org.glowroot.agent.shaded.grpc.ResolvedServerInfo;
import org.glowroot.agent.shaded.grpc.SimpleLoadBalancerFactory;

import java.net.SocketAddress;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;

import javax.annotation.Nullable;

/**
 * The base class for channel builders.
 *
 * @param  The concrete type of this builder.
 */
public abstract class AbstractManagedChannelImplBuilder
        > extends ManagedChannelBuilder {
  private static final String DIRECT_ADDRESS_SCHEME = "directaddress";

  @Nullable
  private Executor executor;
  private final List interceptors = new ArrayList();

  private final String target;

  @Nullable
  private final SocketAddress directServerAddress;

  @Nullable
  private String userAgent;

  @Nullable
  private String authorityOverride;

  @Nullable
  private NameResolver.Factory nameResolverFactory;

  @Nullable
  private LoadBalancer.Factory loadBalancerFactory;

  @Nullable
  private DecompressorRegistry decompressorRegistry;

  @Nullable
  private CompressorRegistry compressorRegistry;

  protected AbstractManagedChannelImplBuilder(String target) {
    this.target = Preconditions.checkNotNull(target);
    this.directServerAddress = null;
  }

  protected AbstractManagedChannelImplBuilder(SocketAddress directServerAddress, String authority) {
    this.target = DIRECT_ADDRESS_SCHEME + ":///" + directServerAddress;
    this.directServerAddress = directServerAddress;
    this.nameResolverFactory = new DirectAddressNameResolverFactory(directServerAddress, authority);
  }

  @Override
  public final T directExecutor() {
    return executor(MoreExecutors.directExecutor());
  }

  @Override
  public final T executor(Executor executor) {
    this.executor = executor;
    return thisT();
  }

  @Override
  public final T intercept(List interceptors) {
    this.interceptors.addAll(interceptors);
    return thisT();
  }

  @Override
  public final T intercept(ClientInterceptor... interceptors) {
    return intercept(Arrays.asList(interceptors));
  }

  @Override
  public final T nameResolverFactory(NameResolver.Factory resolverFactory) {
    Preconditions.checkState(directServerAddress == null,
        "directServerAddress is set (%s), which forbids the use of NameResolverFactory",
        directServerAddress);
    this.nameResolverFactory = resolverFactory;
    return thisT();
  }

  @Override
  public final T loadBalancerFactory(LoadBalancer.Factory loadBalancerFactory) {
    Preconditions.checkState(directServerAddress == null,
        "directServerAddress is set (%s), which forbids the use of LoadBalancerFactory",
        directServerAddress);
    this.loadBalancerFactory = loadBalancerFactory;
    return thisT();
  }

  @Override
  @ExperimentalApi
  public final T decompressorRegistry(DecompressorRegistry registry) {
    this.decompressorRegistry = registry;
    return thisT();
  }

  @Override
  @ExperimentalApi
  public final T compressorRegistry(CompressorRegistry registry) {
    this.compressorRegistry = registry;
    return thisT();
  }

  private T thisT() {
    @SuppressWarnings("unchecked")
    T thisT = (T) this;
    return thisT;
  }

  @Override
  public final T userAgent(String userAgent) {
    this.userAgent = userAgent;
    return thisT();
  }

  @Override
  public final T overrideAuthority(String authority) {
    this.authorityOverride = checkAuthority(authority);
    return thisT();
  }

  /**
   * Verifies the authority is valid.  This method exists as an escape hatch for putting in an
   * authority that is valid, but would fail the default validation provided by this
   * implementation.
   */
  protected String checkAuthority(String authority) {
    return GrpcUtil.checkAuthority(authority);
  }

  @Override
  public ManagedChannelImpl build() {
    ClientTransportFactory transportFactory = new AuthorityOverridingTransportFactory(
        buildTransportFactory(), authorityOverride);
    return new ManagedChannelImpl(
        target,
        // TODO(carl-mastrangelo): Allow clients to pass this in
        new ExponentialBackoffPolicy.Provider(),
        firstNonNull(nameResolverFactory, NameResolverRegistry.getDefaultRegistry()),
        getNameResolverParams(),
        firstNonNull(loadBalancerFactory, SimpleLoadBalancerFactory.getInstance()),
        transportFactory,
        firstNonNull(decompressorRegistry, DecompressorRegistry.getDefaultInstance()),
        firstNonNull(compressorRegistry, CompressorRegistry.getDefaultInstance()),
        executor, userAgent, interceptors);
  }

  /**
   * Subclasses should override this method to provide the {@link ClientTransportFactory}
   * appropriate for this channel. This method is meant for Transport implementors and should not
   * be used by normal users.
   */
  protected abstract ClientTransportFactory buildTransportFactory();

  /**
   * Subclasses can override this method to provide additional parameters to {@link
   * NameResolver.Factory#newNameResolver}. The default implementation returns {@link
   * Attributes#EMPTY}.
   */
  protected Attributes getNameResolverParams() {
    return Attributes.EMPTY;
  }

  private static class AuthorityOverridingTransportFactory implements ClientTransportFactory {
    final ClientTransportFactory factory;
    @Nullable final String authorityOverride;

    AuthorityOverridingTransportFactory(
        ClientTransportFactory factory, @Nullable String authorityOverride) {
      this.factory = factory;
      this.authorityOverride = authorityOverride;
    }

    @Override
    public ManagedClientTransport newClientTransport(SocketAddress serverAddress,
        String authority) {
      return factory.newClientTransport(
          serverAddress, authorityOverride != null ? authorityOverride : authority);
    }

    @Override
    public int referenceCount() {
      return factory.referenceCount();
    }

    @Override
    public ReferenceCounted retain() {
      factory.retain();
      return this;
    }

    @Override
    public ReferenceCounted release() {
      factory.release();
      return this;
    }
  }

  private static class DirectAddressNameResolverFactory extends NameResolver.Factory {
    final SocketAddress address;
    final String authority;

    DirectAddressNameResolverFactory(SocketAddress address, String authority) {
      this.address = address;
      this.authority = authority;
    }

    @Override
    public NameResolver newNameResolver(URI notUsedUri, Attributes params) {
      return new NameResolver() {
        @Override
        public String getServiceAuthority() {
          return authority;
        }

        @Override
        public void start(final Listener listener) {
          listener.onUpdate(
              Collections.singletonList(new ResolvedServerInfo(address, Attributes.EMPTY)),
              Attributes.EMPTY);
        }

        @Override
        public void shutdown() {}
      };
    }

    @Override
    public String getDefaultScheme() {
      return DIRECT_ADDRESS_SCHEME;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy